<p dir="auto"><strong>TypeScript Version:</strong></p>
<p dir="auto">1.8.9</p>
<p dir="auto"><strong>Code</strong></p>
<p dir="auto">With the following function</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function foo(a) {
  return a + 'hello';
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">foo</span><span class="pl-kos">(</span><span class="pl-s1">a</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-s1">a</span> <span class="pl-c1">+</span> <span class="pl-s">'hello'</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">I'd expect that <code class="notranslate">typeChecker.typeToString</code> of <code class="notranslate">foo</code>'s type should yield <code class="notranslate">(a: string) =&gt; string</code>.</p>
<p dir="auto">Instead, it returns <code class="notranslate">(a: any) =&gt; string</code>.</p>
<p dir="auto">Is this an issue of <code class="notranslate">typeToString</code>, or is the underlying Type object really marks <code class="notranslate">a</code> as <code class="notranslate">any</code>?</p>
<p dir="auto">If it's the former, how can I walk the Type object to generate the right signature? A quick glance shows that a procedure type is "anonymous", and holds an opaque reference of <code class="notranslate">target</code> and <code class="notranslate">mapper</code>, which doesn't shed light on how to traverse the type objects. Is there a guide somewhere about the types?</p>
<p dir="auto">I'm trying to generate the type signature for run time contract checking, so I need an accurate representation of the resolved type info.</p>
<p dir="auto">Consider,</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function isString(obj: any): obj is string {
    return typeof typeof obj === &quot;string&quot;; 
}

function foo(value: (string|number)): number {
    if (isString(value)) {
        return value.indexOf('foo')
    } else
        return value;
}

function bar(value: (string|number)): number {
    if (isString(value)) {
        return value.indexOf('foo')
    }
    return value;
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">isString</span><span class="pl-kos">(</span><span class="pl-s1">obj</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span>: <span class="pl-s1">obj</span> is <span class="pl-smi">string</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-k">typeof</span> <span class="pl-k">typeof</span> <span class="pl-s1">obj</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">function</span> <span class="pl-en">foo</span><span class="pl-kos">(</span><span class="pl-s1">value</span>: <span class="pl-kos">(</span><span class="pl-smi">string</span><span class="pl-c1">|</span><span class="pl-smi">number</span><span class="pl-kos">)</span><span class="pl-kos">)</span>: <span class="pl-smi">number</span> <span class="pl-kos">{</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-en">isString</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-s1">value</span><span class="pl-kos">.</span><span class="pl-en">indexOf</span><span class="pl-kos">(</span><span class="pl-s">'foo'</span><span class="pl-kos">)</span>
    <span class="pl-kos">}</span> <span class="pl-k">else</span>
        <span class="pl-k">return</span> <span class="pl-s1">value</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">function</span> <span class="pl-en">bar</span><span class="pl-kos">(</span><span class="pl-s1">value</span>: <span class="pl-kos">(</span><span class="pl-smi">string</span><span class="pl-c1">|</span><span class="pl-smi">number</span><span class="pl-kos">)</span><span class="pl-kos">)</span>: <span class="pl-smi">number</span> <span class="pl-kos">{</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-en">isString</span><span class="pl-kos">(</span><span class="pl-s1">value</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">return</span> <span class="pl-s1">value</span><span class="pl-kos">.</span><span class="pl-en">indexOf</span><span class="pl-kos">(</span><span class="pl-s">'foo'</span><span class="pl-kos">)</span>
    <span class="pl-kos">}</span>
    <span class="pl-k">return</span> <span class="pl-s1">value</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">Expected: Both <code class="notranslate">foo</code> and <code class="notranslate">bar</code> type-check correctly.<br>
Received: <code class="notranslate">bar</code> reports that <code class="notranslate">value</code> is not assignable to <code class="notranslate">number</code>.</p>
<p dir="auto">Flow analysis could be used here to determine <code class="notranslate">value</code> can only be <code class="notranslate">number</code> in all the code paths that arrive at the final <code class="notranslate">return</code>.</p>