<p dir="auto"><strong>TypeScript Version:</strong></p>
<p dir="auto">nightly (1.9.0-dev.20160303)</p>
<p dir="auto"><strong>Code</strong></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="interface Foo {
    foo( key: string ): string;
    foo( keys: string[] ): string[];
}

declare var foo: Foo;
declare const bar: string|string[];

const baz = foo.foo( bar );"><pre class="notranslate"><span class="pl-k">interface</span> <span class="pl-smi">Foo</span> <span class="pl-kos">{</span>
    <span class="pl-c1">foo</span><span class="pl-kos">(</span> <span class="pl-s1">key</span>: <span class="pl-smi">string</span> <span class="pl-kos">)</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
    <span class="pl-c1">foo</span><span class="pl-kos">(</span> <span class="pl-s1">keys</span>: <span class="pl-smi">string</span><span class="pl-kos">[</span><span class="pl-kos">]</span> <span class="pl-kos">)</span>: <span class="pl-smi">string</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">declare</span> <span class="pl-k">var</span> <span class="pl-s1">foo</span>: <span class="pl-smi">Foo</span><span class="pl-kos">;</span>
<span class="pl-k">declare</span> <span class="pl-k">const</span> <span class="pl-s1">bar</span>: <span class="pl-smi">string</span><span class="pl-c1">|</span><span class="pl-smi">string</span><span class="pl-kos">[</span><span class="pl-kos">]</span><span class="pl-kos">;</span>

<span class="pl-k">const</span> <span class="pl-s1">baz</span> <span class="pl-c1">=</span> <span class="pl-s1">foo</span><span class="pl-kos">.</span><span class="pl-en">foo</span><span class="pl-kos">(</span> <span class="pl-s1">bar</span> <span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>Expected behavior:</strong><br>
The code is valid and compiles without warning, because interface <code class="notranslate">Foo</code> contains a signature for a method <code class="notranslate">foo</code> corresponding to each type in the union <code class="notranslate">string|string[]</code>.  The <code class="notranslate">foo</code> method can accept a parameter list of <code class="notranslate">string</code>, and it can also accept a parameter list of <code class="notranslate">string[]</code>, therefore an argument list of <code class="notranslate">string|string[]</code> is satisfiable.</p>
<p dir="auto">I would expect the return type for <code class="notranslate">foo.foo</code> invoked in this faction to be the type union of the return types of all matching signatures (so <code class="notranslate">string|string[]</code>).  This code produces the same error even if all matching signatures have the same return type.</p>
<p dir="auto"><strong>Actual behavior:</strong><br>
<code class="notranslate">Argument of type 'string | string[]' is not assignable to parameter of type 'string[]'  Type 'string' is not assignable to type 'string[]'.</code></p>
<p dir="auto">It would be enormously helpful if <code class="notranslate">this</code> recognized type parameters:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="abstract class Functor&lt;a&gt; {
   abstract map&lt;b&gt;(map: (value: a) =&gt; b): this&lt;b&gt;;
}

abstract class Monad&lt;a&gt; extends Functor&lt;a&gt; {
   abstract bind&lt;b&gt;(bind: (value: a) =&gt; this&lt;b&gt;): this&lt;b&gt;;
}"><pre class="notranslate"><span class="pl-k">abstract</span> <span class="pl-k">class</span> <span class="pl-smi">Functor</span><span class="pl-c1">&lt;</span><span class="pl-smi">a</span><span class="pl-c1">&gt;</span> <span class="pl-kos">{</span>
   <span class="pl-k">abstract</span> <span class="pl-c1">map</span><span class="pl-c1">&lt;</span><span class="pl-smi">b</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">map</span>: <span class="pl-kos">(</span><span class="pl-s1">value</span>: <span class="pl-smi">a</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">b</span><span class="pl-kos">)</span>: <span class="pl-smi">this</span><span class="pl-c1">&lt;</span><span class="pl-smi">b</span><span class="pl-c1">&gt;</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">abstract</span> <span class="pl-k">class</span> <span class="pl-smi">Monad</span><span class="pl-c1">&lt;</span><span class="pl-smi">a</span><span class="pl-c1">&gt;</span> <span class="pl-k">extends</span> <span class="pl-smi">Functor</span><span class="pl-kos">&lt;</span><span class="pl-smi">a</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
   <span class="pl-k">abstract</span> <span class="pl-c1">bind</span><span class="pl-c1">&lt;</span><span class="pl-smi">b</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">bind</span>: <span class="pl-kos">(</span><span class="pl-s1">value</span>: <span class="pl-smi">a</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">this</span><span class="pl-c1">&lt;</span><span class="pl-smi">b</span><span class="pl-c1">&gt;</span><span class="pl-kos">)</span>: <span class="pl-smi">this</span><span class="pl-c1">&lt;</span><span class="pl-smi">b</span><span class="pl-c1">&gt;</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>