<p dir="auto">We currently only support some baked-in forms of type checking for type guards -- <code class="notranslate">typeof</code> and <code class="notranslate">instanceof</code>. In many cases, users will have their own functions that can provide run-time type information.</p>
<p dir="auto">Proposal: a new syntax, valid only in return type annotations, of the form <code class="notranslate">x is T</code> where <code class="notranslate">x</code> is a declared parameter in the signature, or <code class="notranslate">this</code>, and <code class="notranslate">T</code> is any type. This type is actually considered as <code class="notranslate">boolean</code>, but "lights up" type guards. Examples:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function isCat(a: Animal): a is Cat {
  return a.name === 'kitty';
}

var x: Animal;
if(isCat(x)) {
  x.meow(); // OK, x is Cat in this block
}

class Node {
  isLeafNode(): this is LeafNode { throw new Error('abstract'); }
}
class ParentNode extends Node {
  isLeafNode(): this is LeafNode { return false; }
}
class LeafNode extends Node {
  isLeafNode(): this is LeafNode { return true; }
}
var someNode: LeafNode|ParentNode;
if(someNode.isLeafNode()) {
  // someNode: LeafNode in this block
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">isCat</span><span class="pl-kos">(</span><span class="pl-s1">a</span>: <span class="pl-smi">Animal</span><span class="pl-kos">)</span>: <span class="pl-s1">a</span> is <span class="pl-smi">Cat</span> <span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-s1">a</span><span class="pl-kos">.</span><span class="pl-c1">name</span> <span class="pl-c1">===</span> <span class="pl-s">'kitty'</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">var</span> <span class="pl-s1">x</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-en">isCat</span><span class="pl-kos">(</span><span class="pl-s1">x</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-s1">x</span><span class="pl-kos">.</span><span class="pl-en">meow</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// OK, x is Cat in this block</span>
<span class="pl-kos">}</span>

<span class="pl-k">class</span> <span class="pl-smi">Node</span> <span class="pl-kos">{</span>
  <span class="pl-en">isLeafNode</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi">this</span> is <span class="pl-smi">LeafNode</span> <span class="pl-kos">{</span> <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-smi">Error</span><span class="pl-kos">(</span><span class="pl-s">'abstract'</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">class</span> <span class="pl-smi">ParentNode</span> <span class="pl-k">extends</span> <span class="pl-smi">Node</span> <span class="pl-kos">{</span>
  <span class="pl-en">isLeafNode</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi">this</span> is <span class="pl-smi">LeafNode</span> <span class="pl-kos">{</span> <span class="pl-k">return</span> <span class="pl-c1">false</span><span class="pl-kos">;</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span>
<span class="pl-k">class</span> <span class="pl-smi">LeafNode</span> <span class="pl-k">extends</span> <span class="pl-smi">Node</span> <span class="pl-kos">{</span>
  <span class="pl-en">isLeafNode</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-smi">this</span> is <span class="pl-smi">LeafNode</span> <span class="pl-kos">{</span> <span class="pl-k">return</span> <span class="pl-c1">true</span><span class="pl-kos">;</span> <span class="pl-kos">}</span>
<span class="pl-kos">}</span>
<span class="pl-k">var</span> <span class="pl-s1">someNode</span>: <span class="pl-smi">LeafNode</span><span class="pl-c1">|</span><span class="pl-smi">ParentNode</span><span class="pl-kos">;</span>
<span class="pl-k">if</span><span class="pl-kos">(</span><span class="pl-s1">someNode</span><span class="pl-kos">.</span><span class="pl-en">isLeafNode</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
  <span class="pl-c">// someNode: LeafNode in this block</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">The forms <code class="notranslate">if(userCheck([other args,] expr [, other args])) {</code> and <code class="notranslate">if(expr.userCheck([any args]))</code> would apply the type guard to <code class="notranslate">expr</code> the same way that <code class="notranslate">expr instanceof t</code> and <code class="notranslate">typeof expr === 'literal'</code> do today.</p>
<p dir="auto">I'm trying to use local installation of ts compiler and having lots of "TS2300" errors.<br>
Step by step:</p>
<ul dir="auto">
<li>install typescript as a local npm module (<code class="notranslate">npm install typescript</code> <strong>without -g</strong>)</li>
<li>create some .ts source files</li>
<li>create tsconfig.json file</li>
<li>use "rootDir" entry in tsconfig.json to make typescript compile everything inside some project dir</li>
<li>use "outDir" entry in tsconfig.json to point output somewhere inside project dir</li>
<li>run tsc from local installation (<code class="notranslate">./node_modules/typescript/bin/tsc -p ./</code>)</li>
</ul>
<p dir="auto">As result I have lots of "TS2300", looks like tsc for some reason is trying to use some internal .d.ts files twice ore more.<br>
As a workaround I've tried to add "exclude" section to tsconfig with the only "node_modules" inside it. And it worked! No "TS2300" errors anymore.</p>
<p dir="auto">So the bug is (as it seems to me) that tsc is trying to use node_modules even when it's not inside rootDir.</p>
<p dir="auto">PS<br>
Please be aware that I'm new to typescript compiler and thanks in advance =)</p>