<p dir="auto">As of change <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="61346456" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/2356" data-hovercard-type="pull_request" data-hovercard-url="/microsoft/TypeScript/pull/2356/hovercard" href="https://github.com/microsoft/TypeScript/pull/2356">#2356</a>, the following code gives the correct result in the batch compiler:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="declare function f&lt;T&gt;(x: T, y: (p: T) =&gt; T, z: (p: T) =&gt; T): T;
f(0, x =&gt; null, x =&gt; x.blahblah);"><pre class="notranslate"><span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">f</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-s1">x</span>: <span class="pl-smi">T</span><span class="pl-kos">,</span> <span class="pl-s1">y</span>: <span class="pl-kos">(</span><span class="pl-s1">p</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">T</span><span class="pl-kos">,</span> <span class="pl-s1">z</span>: <span class="pl-kos">(</span><span class="pl-s1">p</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">T</span><span class="pl-kos">)</span>: <span class="pl-smi">T</span><span class="pl-kos">;</span>
<span class="pl-en">f</span><span class="pl-kos">(</span><span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-s1">x</span> <span class="pl-c1">=&gt;</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-s1">x</span> <span class="pl-c1">=&gt;</span> <span class="pl-s1">x</span><span class="pl-kos">.</span><span class="pl-c1">blahblah</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">Namely, we infer T to be number, and we get an error on blahblah.</p>
<p dir="auto">However, there are a few things still wrong:</p>
<ul dir="auto">
<li>The language service does not show the correct result. It shows both x's to be number, but if you hover on f, you will see that it was instantiated to <code class="notranslate">any</code>, instead of <code class="notranslate">number</code>.</li>
<li>If you add another overload, the wrong type argument gets inferred:</li>
</ul>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="declare function f&lt;T&gt;(x: T, y: (p: T) =&gt; T, z: (p: T) =&gt; T): T;
declare function f();
f(0, x =&gt; null, x =&gt; x.blahblah);"><pre class="notranslate"><span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">f</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-s1">x</span>: <span class="pl-smi">T</span><span class="pl-kos">,</span> <span class="pl-s1">y</span>: <span class="pl-kos">(</span><span class="pl-s1">p</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">T</span><span class="pl-kos">,</span> <span class="pl-s1">z</span>: <span class="pl-kos">(</span><span class="pl-s1">p</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">T</span><span class="pl-kos">)</span>: <span class="pl-smi">T</span><span class="pl-kos">;</span>
<span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">f</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-en">f</span><span class="pl-kos">(</span><span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-s1">x</span> <span class="pl-c1">=&gt;</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-s1">x</span> <span class="pl-c1">=&gt;</span> <span class="pl-s1">x</span><span class="pl-kos">.</span><span class="pl-c1">blahblah</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">Now suddenly blahblah is not an error, and the second x is <code class="notranslate">any</code>.</p>
<ul dir="auto">
<li>In theory, if this overload is not assignable, but it has already fixed the type parameter T, and another overload comes along with a type parameter in the same position, that second type parameter will not get fixed. I don't have a good repro for this, but it is certainly a possibility in theory.</li>
</ul>
<p dir="auto">All of these issues happen because when a function expression parameter causes a type parameter to get fixed, it only does so if it is affected by the type of that type parameter. I believe the right thing here is that if a function parameter aligns with the type parameter, it should still fix it, even if it has already been assigned a type in the past. That way, it will fix the type parameter no matter which signature is being visited, or whether this signature has been visited before.</p>
<p dir="auto">I consider this bug a followup to bugs <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="58722402" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/2127" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/2127/hovercard" href="https://github.com/microsoft/TypeScript/issues/2127">#2127</a> and <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="59505661" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/2182" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/2182/hovercard" href="https://github.com/microsoft/TypeScript/issues/2182">#2182</a>.</p>
<p dir="auto">As of change <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="61346456" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/2356" data-hovercard-type="pull_request" data-hovercard-url="/microsoft/TypeScript/pull/2356/hovercard" href="https://github.com/microsoft/TypeScript/pull/2356">#2356</a>, the following code gives the correct result in the batch compiler:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="declare function f&lt;T&gt;(x: T, y: (p: T) =&gt; T, z: (p: T) =&gt; T): T;
f(0, x =&gt; null, x =&gt; x.blahblah);"><pre class="notranslate"><span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">f</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-s1">x</span>: <span class="pl-smi">T</span><span class="pl-kos">,</span> <span class="pl-s1">y</span>: <span class="pl-kos">(</span><span class="pl-s1">p</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">T</span><span class="pl-kos">,</span> <span class="pl-s1">z</span>: <span class="pl-kos">(</span><span class="pl-s1">p</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">T</span><span class="pl-kos">)</span>: <span class="pl-smi">T</span><span class="pl-kos">;</span>
<span class="pl-en">f</span><span class="pl-kos">(</span><span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-s1">x</span> <span class="pl-c1">=&gt;</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-s1">x</span> <span class="pl-c1">=&gt;</span> <span class="pl-s1">x</span><span class="pl-kos">.</span><span class="pl-c1">blahblah</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">Namely, we infer T to be number, and we get an error on blahblah.</p>
<p dir="auto">However, there are a few things still wrong:</p>
<ul dir="auto">
<li>The language service does not show the correct result. It shows both x's to be number, but if you hover on f, you will see that it was instantiated to <code class="notranslate">any</code>, instead of <code class="notranslate">number</code>.</li>
<li>If you add another overload, the wrong type argument gets inferred:</li>
</ul>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="declare function f&lt;T&gt;(x: T, y: (p: T) =&gt; T, z: (p: T) =&gt; T): T;
declare function f();
f(0, x =&gt; null, x =&gt; x.blahblah);"><pre class="notranslate"><span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">f</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-s1">x</span>: <span class="pl-smi">T</span><span class="pl-kos">,</span> <span class="pl-s1">y</span>: <span class="pl-kos">(</span><span class="pl-s1">p</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">T</span><span class="pl-kos">,</span> <span class="pl-s1">z</span>: <span class="pl-kos">(</span><span class="pl-s1">p</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">T</span><span class="pl-kos">)</span>: <span class="pl-smi">T</span><span class="pl-kos">;</span>
<span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">f</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-en">f</span><span class="pl-kos">(</span><span class="pl-c1">0</span><span class="pl-kos">,</span> <span class="pl-s1">x</span> <span class="pl-c1">=&gt;</span> <span class="pl-c1">null</span><span class="pl-kos">,</span> <span class="pl-s1">x</span> <span class="pl-c1">=&gt;</span> <span class="pl-s1">x</span><span class="pl-kos">.</span><span class="pl-c1">blahblah</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">Now suddenly blahblah is not an error, and the second x is <code class="notranslate">any</code>.</p>
<ul dir="auto">
<li>In theory, if this overload is not assignable, but it has already fixed the type parameter T, and another overload comes along with a type parameter in the same position, that second type parameter will not get fixed. I don't have a good repro for this, but it is certainly a possibility in theory.</li>
</ul>
<p dir="auto">All of these issues happen because when a function expression parameter causes a type parameter to get fixed, it only does so if it is affected by the type of that type parameter. I believe the right thing here is that even if a function parameter does not align with the type parameter, it should still fix it. That way, it will fix the type parameter no matter which signature is being visited, or whether this signature has been visited before.</p>
<p dir="auto">I consider this bug a followup to bugs <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="58722402" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/2127" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/2127/hovercard" href="https://github.com/microsoft/TypeScript/issues/2127">#2127</a> and <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="59505661" data-permission-text="Title is private" data-url="https://github.com/microsoft/TypeScript/issues/2182" data-hovercard-type="issue" data-hovercard-url="/microsoft/TypeScript/issues/2182/hovercard" href="https://github.com/microsoft/TypeScript/issues/2182">#2182</a>.</p>