<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I tried using the <code class="notranslate">@types/xxxx</code> package and had problems.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I tried using the latest stable version of tsc. <a href="https://www.npmjs.com/package/typescript" rel="nofollow">https://www.npmjs.com/package/typescript</a></li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have a question that is inappropriate for <a href="https://stackoverflow.com/" rel="nofollow">StackOverflow</a>.  (Please ask any appropriate questions there).</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> <a href="https://github.com/blog/821-mention-somebody-they-re-notified">Mention</a> the authors (see <code class="notranslate">Definitions by:</code> in <code class="notranslate">index.d.ts</code>) so they can respond.
<ul dir="auto">
<li>Authors: <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/davidparsson/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/davidparsson">@davidparsson</a> <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/borisyankov/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/borisyankov">@borisyankov</a></li>
</ul>
</li>
</ul>
<p dir="auto">Please consider this case:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class Service {
    setValue(value: string, option?: undefined): void;
    setValue(value: string, option: string): void;
    setValue(value: string, option: string | undefined): void { /* some implementation*/ }
}

const service = new Service();

expect(service.setValue).toHaveBeenCalledWith('v'); 
//                       ^ Gives a ts error &quot;Expected 2 arguments, but got 1. (2254)&quot;

// Even though all of these use cases are valid and work fine:
service.setValue('v');
service.setValue('v', undefined);
service.setValue('v', 'someValue');"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">Service</span> <span class="pl-kos">{</span>
    <span class="pl-c1">setValue</span><span class="pl-kos">(</span><span class="pl-s1">value</span>: <span class="pl-smi">string</span><span class="pl-kos">,</span> <span class="pl-s1">option</span>?: <span class="pl-c1">undefined</span><span class="pl-kos">)</span>: <span class="pl-smi"><span class="pl-k">void</span></span><span class="pl-kos">;</span>
    <span class="pl-c1">setValue</span><span class="pl-kos">(</span><span class="pl-s1">value</span>: <span class="pl-smi">string</span><span class="pl-kos">,</span> <span class="pl-s1">option</span>: <span class="pl-smi">string</span><span class="pl-kos">)</span>: <span class="pl-smi"><span class="pl-k">void</span></span><span class="pl-kos">;</span>
    <span class="pl-en">setValue</span><span class="pl-kos">(</span><span class="pl-s1">value</span>: <span class="pl-smi">string</span><span class="pl-kos">,</span> <span class="pl-s1">option</span>: <span class="pl-smi">string</span> <span class="pl-c1">|</span> <span class="pl-c1">undefined</span><span class="pl-kos">)</span>: <span class="pl-smi"><span class="pl-k">void</span></span> <span class="pl-kos">{</span> <span class="pl-c">/* some implementation*/</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-k">const</span> <span class="pl-s1">service</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-smi">Service</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-en">expect</span><span class="pl-kos">(</span><span class="pl-s1">service</span><span class="pl-kos">.</span><span class="pl-c1">setValue</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toHaveBeenCalledWith</span><span class="pl-kos">(</span><span class="pl-s">'v'</span><span class="pl-kos">)</span><span class="pl-kos">;</span> 
<span class="pl-c">//                       ^ Gives a ts error "Expected 2 arguments, but got 1. (2254)"</span>

<span class="pl-c">// Even though all of these use cases are valid and work fine:</span>
<span class="pl-s1">service</span><span class="pl-kos">.</span><span class="pl-en">setValue</span><span class="pl-kos">(</span><span class="pl-s">'v'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-s1">service</span><span class="pl-kos">.</span><span class="pl-en">setValue</span><span class="pl-kos">(</span><span class="pl-s">'v'</span><span class="pl-kos">,</span> <span class="pl-c1">undefined</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-s1">service</span><span class="pl-kos">.</span><span class="pl-en">setValue</span><span class="pl-kos">(</span><span class="pl-s">'v'</span><span class="pl-kos">,</span> <span class="pl-s">'someValue'</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">For some reason, the <code class="notranslate">toHaveBeenCalledWith()</code> matcher only accepts 2 arguments, even though the method under test (<code class="notranslate">setValue()</code>) has a second argument that is optional.</p>
<p dir="auto">The expected behavior is that <code class="notranslate">expect(service.setValue).toHaveBeenCalledWith('v');</code> should not throw a ts compilation error.</p>
<p dir="auto">Note: one might think that this can be worked around by adding a second parameter of <code class="notranslate">undefined</code> (like <code class="notranslate">expect(service.setValue).toHaveBeenCalledWith('v', undefined);</code>). However, calling <code class="notranslate">service.setValue('v');</code> is different from <code class="notranslate">service.setValue('v', undefined);</code>, since the value of <code class="notranslate">arguments.length</code> object inside the <code class="notranslate">setValue()</code> method is different.</p>
<p dir="auto"><a href="https://github.com/DefinitelyTyped/DefinitelyTyped/commit/7456aa4eec4bcfc03259a7d32e619d0607bbed3b#r37354130">The function signature for <code class="notranslate">toHaveBeenCalledWith</code></a> unfortunately breaks if a generic function that consists of overloads is passed. TypeScript is not able to infer the proper overload for functions through generics. Only a single overload signature is considered for parameter inferring. For example:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function hello(idx: number): void;
function hello(item: object): void;
function hello(arg: any): void { /* impl */}

// This won't work because `MatchableArgs` only infers `object` as parameter type.
expect(hello).toHaveBeenCalledWith(1);"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-s1">hello</span><span class="pl-kos">(</span><span class="pl-s1">idx</span>: <span class="pl-smi">number</span><span class="pl-kos">)</span>: <span class="pl-smi"><span class="pl-k">void</span></span><span class="pl-kos">;</span>
<span class="pl-k">function</span> <span class="pl-s1">hello</span><span class="pl-kos">(</span><span class="pl-s1">item</span>: <span class="pl-smi">object</span><span class="pl-kos">)</span>: <span class="pl-smi"><span class="pl-k">void</span></span><span class="pl-kos">;</span>
<span class="pl-k">function</span> <span class="pl-en">hello</span><span class="pl-kos">(</span><span class="pl-s1">arg</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span>: <span class="pl-smi"><span class="pl-k">void</span></span> <span class="pl-kos">{</span> <span class="pl-c">/* impl */</span><span class="pl-kos">}</span>

<span class="pl-c">// This won't work because `MatchableArgs` only infers `object` as parameter type.</span>
<span class="pl-en">expect</span><span class="pl-kos">(</span><span class="pl-s1">hello</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">toHaveBeenCalledWith</span><span class="pl-kos">(</span><span class="pl-c1">1</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">This is a <a href="https://github.com/microsoft/TypeScript/issues/32418" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/32418/hovercard">known limitation in TypeScript</a>, but it feels inconvenient that workarounds are needed for function overloads. Overloads are not a rare concept seen in TypeScript projects. I'm wondering if it would make sense to go back to the non-inferred parameter types. i.e. simply using <code class="notranslate">any[]</code>.</p>
<p dir="auto">Authors: <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/zvirja/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/zvirja">@zvirja</a> <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/djungowski/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/djungowski">@djungowski</a> <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/kolodny/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/kolodny">@kolodny</a></p>