<p dir="auto">Stupid question of the day, why does this not work:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class A {
    foo: string;
}

class B {
    bar: string;
}

class C {
    qat: string;
}

class D {
    baz: string;
}

function c(a: A): C;  /* Overloaded signature not compatible with function implementation */
function c(b: B): D;
function c(a: A|B): C|D {
    if (a instanceof A) {
        return new C();
    }
    else {
        return new D();
    }
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">A</span> <span class="pl-kos">{</span>
    <span class="pl-c1">foo</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">class</span> <span class="pl-smi">B</span> <span class="pl-kos">{</span>
    <span class="pl-c1">bar</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">class</span> <span class="pl-smi">C</span> <span class="pl-kos">{</span>
    <span class="pl-c1">qat</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">class</span> <span class="pl-smi">D</span> <span class="pl-kos">{</span>
    <span class="pl-c1">baz</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">function</span> <span class="pl-s1">c</span><span class="pl-kos">(</span><span class="pl-s1">a</span>: <span class="pl-smi">A</span><span class="pl-kos">)</span>: <span class="pl-smi">C</span><span class="pl-kos">;</span>  <span class="pl-c">/* Overloaded signature not compatible with function implementation */</span>
<span class="pl-k">function</span> <span class="pl-s1">c</span><span class="pl-kos">(</span><span class="pl-s1">b</span>: <span class="pl-smi">B</span><span class="pl-kos">)</span>: <span class="pl-smi">D</span><span class="pl-kos">;</span>
<span class="pl-k">function</span> <span class="pl-en">c</span><span class="pl-kos">(</span><span class="pl-s1">a</span>: <span class="pl-smi">A</span><span class="pl-c1">|</span><span class="pl-smi">B</span><span class="pl-kos">)</span>: <span class="pl-smi">C</span><span class="pl-c1">|</span><span class="pl-smi">D</span> <span class="pl-kos">{</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">a</span> <span class="pl-k">instanceof</span> <span class="pl-smi">A</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-smi">C</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
    <span class="pl-k">else</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-smi">D</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Where as this is valid:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function c(a: A): C|D;
function c(b: B): C|D;
function c(a: A|B): C|D {
    if (a instanceof A) {
        return new C();
    }
    else {
        return new D();
    }
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-s1">c</span><span class="pl-kos">(</span><span class="pl-s1">a</span>: <span class="pl-smi">A</span><span class="pl-kos">)</span>: <span class="pl-smi">C</span><span class="pl-c1">|</span><span class="pl-smi">D</span><span class="pl-kos">;</span>
<span class="pl-k">function</span> <span class="pl-s1">c</span><span class="pl-kos">(</span><span class="pl-s1">b</span>: <span class="pl-smi">B</span><span class="pl-kos">)</span>: <span class="pl-smi">C</span><span class="pl-c1">|</span><span class="pl-smi">D</span><span class="pl-kos">;</span>
<span class="pl-k">function</span> <span class="pl-en">c</span><span class="pl-kos">(</span><span class="pl-s1">a</span>: <span class="pl-smi">A</span><span class="pl-c1">|</span><span class="pl-smi">B</span><span class="pl-kos">)</span>: <span class="pl-smi">C</span><span class="pl-c1">|</span><span class="pl-smi">D</span> <span class="pl-kos">{</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">a</span> <span class="pl-k">instanceof</span> <span class="pl-smi">A</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-smi">C</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
    <span class="pl-k">else</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-smi">D</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">I am allowed to "delegate" the sorting out of the typing of my argument to my overloaded function implementation, but, I am not allowed to delegate the return type, though I am contracting to only return to return a certain type of return value (which is what I am doing with the handling arguments).  Is there a good reason I am missing?</p>
<p dir="auto">Consider some code:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="/* ... disjoint classes Giraffe, Elephant which extend Animal ... */
function f(n: string): Giraffe;
function f(n: number): Elephant;
function f(n: any): Animal {
  if(typeof n === 'string') {
    return new Giraffe(n);
  } else if(typeof n === 'number') {
    return new Elephant(n);
  }
}"><pre class="notranslate"><span class="pl-c">/* ... disjoint classes Giraffe, Elephant which extend Animal ... */</span>
<span class="pl-k">function</span> <span class="pl-s1">f</span><span class="pl-kos">(</span><span class="pl-s1">n</span>: <span class="pl-smi">string</span><span class="pl-kos">)</span>: <span class="pl-smi">Giraffe</span><span class="pl-kos">;</span>
<span class="pl-k">function</span> <span class="pl-s1">f</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">Elephant</span><span class="pl-kos">;</span>
<span class="pl-k">function</span> <span class="pl-en">f</span><span class="pl-kos">(</span><span class="pl-s1">n</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span>: <span class="pl-smi">Animal</span> <span class="pl-kos">{</span>
  <span class="pl-k">if</span><span class="pl-kos">(</span><span class="pl-k">typeof</span> <span class="pl-s1">n</span> <span class="pl-c1">===</span> <span class="pl-s">'string'</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-smi">Giraffe</span><span class="pl-kos">(</span><span class="pl-s1">n</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span> <span class="pl-k">else</span> <span class="pl-k">if</span><span class="pl-kos">(</span><span class="pl-k">typeof</span> <span class="pl-s1">n</span> <span class="pl-c1">===</span> <span class="pl-s">'number'</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-k">new</span> <span class="pl-smi">Elephant</span><span class="pl-kos">(</span><span class="pl-s1">n</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Perhaps surprisingly, this yields errors on the overload signatures because the function implementation signature is not assignable <em>to</em> the overload signatures. This is unfortunate for implementors as they must use <code class="notranslate">:any</code> when implementing a function with disjoint parameter types in its overloads. Now that union types are possible, the implementor of <code class="notranslate">f</code> could even write <code class="notranslate">Giraffe|Elephant</code> to get more specific type checking of their return expressions.</p>
<p dir="auto">One option is to change the relation in 6.1 from "assignable to" to "assignable to or from". This solves the issue above, but has a negative side effect of allowing an implementation signature to have more required parameters than any of the overloads. This might be a desirable trade-off compared to not allowing implementations to have good return expression checking. Alternatively, we could create some new kind of relation that is bivariant for return types but maintains the existing requirements of parameter arity.</p>
<p dir="auto">Note that we do want to use the opposite assignability relation here as the implementation signature may be of an inconsequentially more-specific type.</p>