<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="interface Promise&lt;T&gt; {
    then&lt;U&gt;(cb: (x: T) =&gt; Promise&lt;U&gt;): Promise&lt;U&gt;;
}

// Consider both orderings of the following overloads
declare function testFunction(n: number): Promise&lt;number&gt;;
declare function testFunction(s: string): Promise&lt;string&gt;;

var numPromise: Promise&lt;number&gt;;
var newPromise = numPromise.then(testFunction);"><pre class="notranslate"><span class="pl-k">interface</span> <span class="pl-smi">Promise</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span><span class="pl-c1">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c1">then</span><span class="pl-c1">&lt;</span><span class="pl-smi">U</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">cb</span>: <span class="pl-kos">(</span><span class="pl-s1">x</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">Promise</span><span class="pl-kos">&lt;</span><span class="pl-smi">U</span><span class="pl-kos">&gt;</span><span class="pl-kos">)</span>: <span class="pl-smi">Promise</span><span class="pl-kos">&lt;</span><span class="pl-smi">U</span><span class="pl-kos">&gt;</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-c">// Consider both orderings of the following overloads</span>
<span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">testFunction</span><span class="pl-kos">(</span><span class="pl-s1">n</span>: <span class="pl-smi">number</span><span class="pl-kos">)</span>: <span class="pl-smi">Promise</span><span class="pl-kos">&lt;</span><span class="pl-smi">number</span><span class="pl-kos">&gt;</span><span class="pl-kos">;</span>
<span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">testFunction</span><span class="pl-kos">(</span><span class="pl-s1">s</span>: <span class="pl-smi">string</span><span class="pl-kos">)</span>: <span class="pl-smi">Promise</span><span class="pl-kos">&lt;</span><span class="pl-smi">string</span><span class="pl-kos">&gt;</span><span class="pl-kos">;</span>

<span class="pl-k">var</span> <span class="pl-s1">numPromise</span>: <span class="pl-smi">Promise</span><span class="pl-kos">&lt;</span><span class="pl-smi">number</span><span class="pl-kos">&gt;</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-s1">newPromise</span> <span class="pl-c1">=</span> <span class="pl-s1">numPromise</span><span class="pl-kos">.</span><span class="pl-en">then</span><span class="pl-kos">(</span><span class="pl-s1">testFunction</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">In the old compiler, with either ordering of the overloads, newPromise had type <code class="notranslate">Promise&lt;{}&gt;</code>.<br>
In the new compiler, if the number signature comes first, we get an error. If the string signature comes first, newPromise is of type <code class="notranslate">Promise&lt;number&gt;</code>! This is very inconsistent.<br>
We have based this on the notion that the last overload will always be more general than the preceding overloads. However, with disjoint overloads, we are essentially giving the last one undue priority. The rule of thumb is that in a call, the first overload has priority, so giving the last one priority when passing a callback seems really unintuitive.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="interface Opts { url: string; }

declare function doit(url: string): number;
declare function doit(opts: Opts): boolean;

declare function call&lt;T, U&gt;(fn: (arg: T) =&gt; U, arg: T): U;

var n: number = call(doit, 'here');
var b: boolean = call(doit, { url: 'here' });"><pre class="notranslate"><span class="pl-k">interface</span> <span class="pl-smi">Opts</span> <span class="pl-kos">{</span> <span class="pl-c1">url</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span> <span class="pl-kos">}</span>

<span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">doit</span><span class="pl-kos">(</span><span class="pl-s1">url</span>: <span class="pl-smi">string</span><span class="pl-kos">)</span>: <span class="pl-smi">number</span><span class="pl-kos">;</span>
<span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">doit</span><span class="pl-kos">(</span><span class="pl-s1">opts</span>: <span class="pl-smi">Opts</span><span class="pl-kos">)</span>: <span class="pl-smi">boolean</span><span class="pl-kos">;</span>

<span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">call</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span><span class="pl-kos">,</span> <span class="pl-smi">U</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">fn</span>: <span class="pl-kos">(</span><span class="pl-s1">arg</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">U</span><span class="pl-kos">,</span> <span class="pl-s1">arg</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span>: <span class="pl-smi">U</span><span class="pl-kos">;</span>

<span class="pl-k">var</span> <span class="pl-s1">n</span>: <span class="pl-smi">number</span> <span class="pl-c1">=</span> <span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-s1">doit</span><span class="pl-kos">,</span> <span class="pl-s">'here'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-k">var</span> <span class="pl-s1">b</span>: <span class="pl-smi">boolean</span> <span class="pl-c1">=</span> <span class="pl-en">call</span><span class="pl-kos">(</span><span class="pl-s1">doit</span><span class="pl-kos">,</span> <span class="pl-kos">{</span> <span class="pl-c1">url</span>: <span class="pl-s">'here'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">In 1.4.1.0 this snippet errors out with</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="test.ts(8,17): error TS2453: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly.
  Type argument candidate 'Opts' is not a valid type argument because it is not a supertype of candidate 'string'."><pre class="notranslate"><code class="notranslate">test.ts(8,17): error TS2453: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly.
  Type argument candidate 'Opts' is not a valid type argument because it is not a supertype of candidate 'string'.
</code></pre></div>
<p dir="auto">changing line 8 to <code class="notranslate">... = call&lt;string, number&gt;(doit, 'here');</code> successfully compiles as expected.</p>
<p dir="auto">While playing around with this I noticed that while 1.3.0.0 would allow the <code class="notranslate">call(doit, 'here')</code> invocation it was still choosing the second overload of <code class="notranslate">doit</code> resulting in a return type of <code class="notranslate">boolean</code> and causing a compile error on the assignment. I'm glad 1.4.1.0 is now catching this error case, but it seems like inference of the type parameters should be entirely possible here.</p>