<p dir="auto"><strong>TypeScript Version:</strong></p>
<p dir="auto">1.8.7</p>
<p dir="auto">compiled: <code class="notranslate">tsc --noImplicitAny error.ts</code><br>
(the behavior is exactly the same with or without <code class="notranslate">--noImplictAny</code>)</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="// A self-contained demonstration of the problem follows...
type Greeting = &quot;hello&quot; | &quot;goodbye&quot;

const apply = &lt;T extends string,R&gt;(t: T, f: (t:T) =&gt; R): R =&gt; f(t)
const f1 = (a: Greeting) =&gt; console.log('greetings')
const f2 = (a: number) =&gt; console.log(3+a)

apply(&quot;hello&quot;, f1) /* 1. should be good. is good */
apply(&quot;helo&quot;, f1) /* 2a. should be error. is good */
apply&lt;Greeting, void&gt;(&quot;helo&quot;, f1) /* 2b. should be error. is error */

apply(&quot;hello&quot;, f2) /* 3. should be error. is error */
apply(3, f1) /* 4. should be error. is error */
apply(3, f2) /* 5. should be error. is error */
"><pre class="notranslate"><span class="pl-c">// A self-contained demonstration of the problem follows...</span>
<span class="pl-k">type</span> <span class="pl-smi">Greeting</span> <span class="pl-c1">=</span> <span class="pl-s">"hello"</span> <span class="pl-c1">|</span> <span class="pl-s">"goodbye"</span>

<span class="pl-k">const</span> <span class="pl-en">apply</span> <span class="pl-c1">=</span> <span class="pl-c1">&lt;</span><span class="pl-smi">T</span> <span class="pl-k">extends</span> <span class="pl-smi">string</span><span class="pl-kos">,</span><span class="pl-smi">R</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">t</span>: <span class="pl-smi">T</span><span class="pl-kos">,</span> <span class="pl-s1">f</span>: <span class="pl-kos">(</span><span class="pl-s1">t</span>:<span class="pl-smi">T</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">R</span><span class="pl-kos">)</span>: <span class="pl-smi">R</span> <span class="pl-c1">=&gt;</span> <span class="pl-en">f</span><span class="pl-kos">(</span><span class="pl-s1">t</span><span class="pl-kos">)</span>
<span class="pl-k">const</span> <span class="pl-en">f1</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">a</span>: <span class="pl-smi">Greeting</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s">'greetings'</span><span class="pl-kos">)</span>
<span class="pl-k">const</span> <span class="pl-en">f2</span> <span class="pl-c1">=</span> <span class="pl-kos">(</span><span class="pl-s1">a</span>: <span class="pl-smi">number</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-c1">3</span><span class="pl-c1">+</span><span class="pl-s1">a</span><span class="pl-kos">)</span>

<span class="pl-en">apply</span><span class="pl-kos">(</span><span class="pl-s">"hello"</span><span class="pl-kos">,</span> <span class="pl-s1">f1</span><span class="pl-kos">)</span> <span class="pl-c">/* 1. should be good. is good */</span>
<span class="pl-en">apply</span><span class="pl-kos">(</span><span class="pl-s">"helo"</span><span class="pl-kos">,</span> <span class="pl-s1">f1</span><span class="pl-kos">)</span> <span class="pl-c">/* 2a. should be error. is good */</span>
<span class="pl-en">apply</span><span class="pl-kos">&lt;</span><span class="pl-smi">Greeting</span><span class="pl-kos">,</span> <span class="pl-smi"><span class="pl-k">void</span></span><span class="pl-kos">&gt;</span><span class="pl-kos">(</span><span class="pl-s">"helo"</span><span class="pl-kos">,</span> <span class="pl-s1">f1</span><span class="pl-kos">)</span> <span class="pl-c">/* 2b. should be error. is error */</span>

<span class="pl-en">apply</span><span class="pl-kos">(</span><span class="pl-s">"hello"</span><span class="pl-kos">,</span> <span class="pl-s1">f2</span><span class="pl-kos">)</span> <span class="pl-c">/* 3. should be error. is error */</span>
<span class="pl-en">apply</span><span class="pl-kos">(</span><span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-s1">f1</span><span class="pl-kos">)</span> <span class="pl-c">/* 4. should be error. is error */</span>
<span class="pl-en">apply</span><span class="pl-kos">(</span><span class="pl-c1">3</span><span class="pl-kos">,</span> <span class="pl-s1">f2</span><span class="pl-kos">)</span> <span class="pl-c">/* 5. should be error. is error */</span></pre></div>
<p dir="auto"><strong>Expected behavior:</strong><br>
2-5 should have an error:</p>
<p dir="auto">2 should have an error because <code class="notranslate">"helo"</code> is not a member of <code class="notranslate">"hello"|"goodbye"</code><br>
3 should have an error because <code class="notranslate">"hello"</code> is not a <code class="notranslate">number</code><br>
4 should have an error because <code class="notranslate">3</code> is not a member of <code class="notranslate">"hello"|"goodbye"</code> and because <code class="notranslate">3</code> is not a member of type which <code class="notranslate">extends string</code><br>
5 should have an error because <code class="notranslate">3</code> is not a member of a type which <code class="notranslate">extends string</code>, and because <code class="notranslate">number</code> does not <code class="notranslate">extend string</code>.</p>
<p dir="auto"><strong>Actual behavior:</strong><br>
1, 2b, 3-5 are correct<br>
2a passes typechecking even though it should be equivalent to 2b</p>
<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">Based on <a href="https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API">Using the Compiler API</a>, to generate an AST, use <code class="notranslate">createSourceFile</code> like this:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="// A self-contained demonstration of the problem follows...
ts.createSourceFile(&lt;filename&gt;, &lt;file content&gt;, ts.ScriptTarget.ES6, true)"><pre class="notranslate"><span class="pl-c">// A self-contained demonstration of the problem follows...</span>
<span class="pl-s1">ts</span><span class="pl-kos">.</span><span class="pl-en">createSourceFile</span><span class="pl-kos">(</span><span class="pl-c1">&lt;</span><span class="pl-smi">filename</span><span class="pl-c1">&gt;</span><span class="pl-kos">,</span> <span class="pl-c1">&lt;</span><span class="pl-s1">file</span> <span class="pl-smi">content</span><span class="pl-c1">&gt;</span><span class="pl-kos">,</span> <span class="pl-s1">ts</span><span class="pl-kos">.</span><span class="pl-c1">ScriptTarget</span><span class="pl-kos">.</span><span class="pl-c1">ES6</span><span class="pl-kos">,</span> <span class="pl-c1">true</span><span class="pl-kos">)</span></pre></div>
<p dir="auto">What gets generated appears to be an untyped AST, i.e. the <code class="notranslate">.type</code> field only gets filled if it's declared explicitly in the source code.</p>
<p dir="auto">What I'm looking for is to generated the typed AST, i.e. having the sources being loaded and typed-checked.</p>
<p dir="auto">How can I do that? Thanks.</p>