<p dir="auto"><strong>TypeScript Version:</strong></p>
<p dir="auto">1.8.2</p>
<p dir="auto"><strong>Background</strong>:</p>
<p dir="auto">I have been working on trying to get <a href="https://github.com/eslint/typescript-eslint-parser">https://github.com/eslint/typescript-eslint-parser</a>, a TypeScript parser plugin for ESLint, off the ground, and the current job is adding JSX support.</p>
<p dir="auto">ESLint uses espree and so the aim of the project is to convert the output of the tsc to an AST which espree expects. We already have a solid suite of JSX tests to develop against (taken from the espree project itself).</p>
<p dir="auto">We do make use of some helper TypeScript helper methods when converting the AST, such as <code class="notranslate">ts.findNextToken()</code> and I believe I may have found an issue with the way it handles <strong>JsxText</strong></p>
<p dir="auto">Given this JSX code:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&lt;div&gt;@test content&lt;/div&gt;;
"><pre class="notranslate"><span class="pl-kos">&lt;</span><span class="pl-smi">div</span><span class="pl-kos">&gt;</span>@<span class="pl-s1">test</span> <span class="pl-s1">content</span><span class="pl-c1">&lt;</span><span class="pl-c1">/</span>div&gt;;</pre></div>
<p dir="auto">...the TSC produces the AST we expect - with <code class="notranslate">@test content</code> represented as a single JsxText node:</p>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://cloud.githubusercontent.com/assets/900523/13686212/afe93c4a-e70c-11e5-8ce1-36a54a2094ab.png"><img src="https://cloud.githubusercontent.com/assets/900523/13686212/afe93c4a-e70c-11e5-8ce1-36a54a2094ab.png" alt="unspecified-1" style="max-width: 100%;"></a></p>
<p dir="auto">However, when iterating through the AST using <code class="notranslate">ts.findNextToken()</code>, rather than a single JsxText node, we get a node for <code class="notranslate">@</code>, <code class="notranslate">test</code> and <code class="notranslate">content</code> separately.</p>
<p dir="auto">Upon quick inspection of the source I noticed that the related function, <code class="notranslate">ts.findPrecedingToken()</code>, was doing an early check for a JsxText node type, whereas <code class="notranslate">ts.findNextToken()</code> wasn't.</p>
<p dir="auto">(See <a href="https://github.com/Microsoft/TypeScript/blob/master/src/services/utilities.ts#L338">https://github.com/Microsoft/TypeScript/blob/master/src/services/utilities.ts#L338</a> vs <a href="https://github.com/Microsoft/TypeScript/blob/master/src/services/utilities.ts#L364">https://github.com/Microsoft/TypeScript/blob/master/src/services/utilities.ts#L364</a>)</p>
<p dir="auto">Sure enough when I monkey patched the relevant bit of typescript.js to exit early if n.kind was JsxText, a single JsxText token was recognised for <code class="notranslate">@test content</code>, and my test passed.</p>
<p dir="auto">If you agree that this is a bug, then I would be very happy submit a PR, otherwise any tips on how I might have arrived at this false positive would be very much appreciated!</p>
<p dir="auto"><strong>TypeScript Version:</strong></p>
<p dir="auto">1.9.0-dev.20160502</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="declare namespace Windows.Foundation {
    interface IPromise&lt;TResult&gt; {
        then&lt;U&gt;(success?: (value: TResult) =&gt; IPromise&lt;U&gt;, error?: (error: any) =&gt; IPromise&lt;U&gt;, progress?: (progress: any) =&gt; void): IPromise&lt;U&gt;;
        then&lt;U&gt;(success?: (value: TResult) =&gt; IPromise&lt;U&gt;, error?: (error: any) =&gt; U, progress?: (progress: any) =&gt; void): IPromise&lt;U&gt;;
        then&lt;U&gt;(success?: (value: TResult) =&gt; U, error?: (error: any) =&gt; IPromise&lt;U&gt;, progress?: (progress: any) =&gt; void): IPromise&lt;U&gt;;
        then&lt;U&gt;(success?: (value: TResult) =&gt; U, error?: (error: any) =&gt; U, progress?: (progress: any) =&gt; void): IPromise&lt;U&gt;;
        done&lt;U&gt;(success?: (value: TResult) =&gt; any, error?: (error: any) =&gt; any, progress?: (progress: any) =&gt; void): void;

        cancel(): void;
    }
}

async function sample(promise: Windows.Foundation.IPromise&lt;number&gt;) {
    var number = await promise;
}"><pre class="notranslate"><span class="pl-k">declare</span> <span class="pl-k">namespace</span> <span class="pl-smi">Windows</span><span class="pl-kos">.</span><span class="pl-smi">Foundation</span> <span class="pl-kos">{</span>
    <span class="pl-k">interface</span> <span class="pl-smi">IPromise</span><span class="pl-c1">&lt;</span><span class="pl-smi">TResult</span><span class="pl-c1">&gt;</span> <span class="pl-kos">{</span>
        <span class="pl-c1">then</span><span class="pl-c1">&lt;</span><span class="pl-smi">U</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">success</span>?: <span class="pl-kos">(</span><span class="pl-s1">value</span>: <span class="pl-smi">TResult</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">IPromise</span><span class="pl-kos">&lt;</span><span class="pl-smi">U</span><span class="pl-kos">&gt;</span><span class="pl-kos">,</span> <span class="pl-s1">error</span>?: <span class="pl-kos">(</span><span class="pl-s1">error</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">IPromise</span><span class="pl-kos">&lt;</span><span class="pl-smi">U</span><span class="pl-kos">&gt;</span><span class="pl-kos">,</span> <span class="pl-s1">progress</span>?: <span class="pl-kos">(</span><span class="pl-s1">progress</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi"><span class="pl-k">void</span></span><span class="pl-kos">)</span>: <span class="pl-smi">IPromise</span><span class="pl-kos">&lt;</span><span class="pl-smi">U</span><span class="pl-kos">&gt;</span><span class="pl-kos">;</span>
        <span class="pl-c1">then</span><span class="pl-c1">&lt;</span><span class="pl-smi">U</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">success</span>?: <span class="pl-kos">(</span><span class="pl-s1">value</span>: <span class="pl-smi">TResult</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">IPromise</span><span class="pl-kos">&lt;</span><span class="pl-smi">U</span><span class="pl-kos">&gt;</span><span class="pl-kos">,</span> <span class="pl-s1">error</span>?: <span class="pl-kos">(</span><span class="pl-s1">error</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">U</span><span class="pl-kos">,</span> <span class="pl-s1">progress</span>?: <span class="pl-kos">(</span><span class="pl-s1">progress</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi"><span class="pl-k">void</span></span><span class="pl-kos">)</span>: <span class="pl-smi">IPromise</span><span class="pl-kos">&lt;</span><span class="pl-smi">U</span><span class="pl-kos">&gt;</span><span class="pl-kos">;</span>
        <span class="pl-c1">then</span><span class="pl-c1">&lt;</span><span class="pl-smi">U</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">success</span>?: <span class="pl-kos">(</span><span class="pl-s1">value</span>: <span class="pl-smi">TResult</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">U</span><span class="pl-kos">,</span> <span class="pl-s1">error</span>?: <span class="pl-kos">(</span><span class="pl-s1">error</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">IPromise</span><span class="pl-kos">&lt;</span><span class="pl-smi">U</span><span class="pl-kos">&gt;</span><span class="pl-kos">,</span> <span class="pl-s1">progress</span>?: <span class="pl-kos">(</span><span class="pl-s1">progress</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi"><span class="pl-k">void</span></span><span class="pl-kos">)</span>: <span class="pl-smi">IPromise</span><span class="pl-kos">&lt;</span><span class="pl-smi">U</span><span class="pl-kos">&gt;</span><span class="pl-kos">;</span>
        <span class="pl-c1">then</span><span class="pl-c1">&lt;</span><span class="pl-smi">U</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">success</span>?: <span class="pl-kos">(</span><span class="pl-s1">value</span>: <span class="pl-smi">TResult</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">U</span><span class="pl-kos">,</span> <span class="pl-s1">error</span>?: <span class="pl-kos">(</span><span class="pl-s1">error</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">U</span><span class="pl-kos">,</span> <span class="pl-s1">progress</span>?: <span class="pl-kos">(</span><span class="pl-s1">progress</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi"><span class="pl-k">void</span></span><span class="pl-kos">)</span>: <span class="pl-smi">IPromise</span><span class="pl-kos">&lt;</span><span class="pl-smi">U</span><span class="pl-kos">&gt;</span><span class="pl-kos">;</span>
        <span class="pl-c1">done</span><span class="pl-c1">&lt;</span><span class="pl-smi">U</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">success</span>?: <span class="pl-kos">(</span><span class="pl-s1">value</span>: <span class="pl-smi">TResult</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">any</span><span class="pl-kos">,</span> <span class="pl-s1">error</span>?: <span class="pl-kos">(</span><span class="pl-s1">error</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">any</span><span class="pl-kos">,</span> <span class="pl-s1">progress</span>?: <span class="pl-kos">(</span><span class="pl-s1">progress</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi"><span class="pl-k">void</span></span><span class="pl-kos">)</span>: <span class="pl-smi"><span class="pl-k">void</span></span><span class="pl-kos">;</span>

        <span class="pl-c1">cancel</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi"><span class="pl-k">void</span></span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-k">async</span> <span class="pl-k">function</span> <span class="pl-en">sample</span><span class="pl-kos">(</span><span class="pl-s1">promise</span>: <span class="pl-smi">Windows</span><span class="pl-kos">.</span><span class="pl-smi">Foundation</span><span class="pl-kos">.</span><span class="pl-smi">IPromise</span><span class="pl-kos">&lt;</span><span class="pl-smi">number</span><span class="pl-kos">&gt;</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">var</span> <span class="pl-s1">number</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-s1">promise</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto"><strong>Expected behavior:</strong><br>
No error, as this is an await-compatible Promise definition; more concretely, those are definitions for UWP APIs and they worked well with a stable TypeScript.</p>
<p dir="auto"><strong>Actual behavior:</strong><br>
Compiler emits an error <code class="notranslate">Operand for 'await' does not have a valid callable 'then' member.</code>.</p>