<p dir="auto">Just read about <a href="https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#improved-unionintersection-type-inference">this new TypeScript feature</a> and tried to use it in my project, but...</p>
<p dir="auto"><strong>TypeScript Version:</strong></p>
<p dir="auto">1.8.9</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="type T = {a:any} | {b:any};

let myObject:{c:T};

function hasA(value:T):value is {a:any}{
  return 'a' in value;
}
if(hasA(myObject.c)){
  myObject.c.a; // &lt;- the error goes from here
}"><pre class="notranslate"><span class="pl-k">type</span> <span class="pl-smi">T</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-c1">a</span>:<span class="pl-smi">any</span><span class="pl-kos">}</span> <span class="pl-c1">|</span> <span class="pl-kos">{</span><span class="pl-c1">b</span>:<span class="pl-smi">any</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">let</span> <span class="pl-s1">myObject</span>:<span class="pl-kos">{</span><span class="pl-c1">c</span>:<span class="pl-smi">T</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-k">function</span> <span class="pl-en">hasA</span><span class="pl-kos">(</span><span class="pl-s1">value</span>:<span class="pl-smi">T</span><span class="pl-kos">)</span>:<span class="pl-s1">value</span> is <span class="pl-kos">{</span><span class="pl-c1">a</span>:<span class="pl-smi">any</span><span class="pl-kos">}</span><span class="pl-kos">{</span>
  <span class="pl-k">return</span> <span class="pl-s">'a'</span> <span class="pl-k">in</span> <span class="pl-s1">value</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>
<span class="pl-k">if</span><span class="pl-kos">(</span><span class="pl-en">hasA</span><span class="pl-kos">(</span><span class="pl-s1">myObject</span><span class="pl-kos">.</span><span class="pl-c1">c</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">{</span>
  <span class="pl-s1">myObject</span><span class="pl-kos">.</span><span class="pl-c1">c</span><span class="pl-kos">.</span><span class="pl-c1">a</span><span class="pl-kos">;</span> <span class="pl-c">// &lt;- the error goes from here</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto"><strong>Expected behavior:</strong></p>
<p dir="auto">No error.</p>
<p dir="auto"><strong>Actual behavior:</strong></p>
<p dir="auto"><code class="notranslate">Error:(24, 14) TS2339: Property 'a' does not exist on type '{ a: any; } | { b: any; }'.</code></p>
<p dir="auto">Shouldn't it be considered as a bug?</p>
<p dir="auto">I just found out that property access expressions doesn't work on type predicate functions and <code class="notranslate">instanceof</code> type guards.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="
class A {
    propA: number;
}

class B {
    propB: number;
}
class C {
    propC: A;
}

declare function isA(p1: any): p1 is D;

interface D {
    a: A | B
    b: A | C;
}

let d: D;
if (isA(d.b)) {
    d.b.propA; //error
}

function foo(d: D) {
    if (d.b instanceof A) {
        d.b.propA // error
    }
}"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">A</span> <span class="pl-kos">{</span>
    <span class="pl-c1">propA</span>: <span class="pl-smi">number</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">class</span> <span class="pl-smi">B</span> <span class="pl-kos">{</span>
    <span class="pl-c1">propB</span>: <span class="pl-smi">number</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>
<span class="pl-k">class</span> <span class="pl-smi">C</span> <span class="pl-kos">{</span>
    <span class="pl-c1">propC</span>: <span class="pl-smi">A</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">declare</span> <span class="pl-k">function</span> <span class="pl-s1">isA</span><span class="pl-kos">(</span><span class="pl-s1">p1</span>: <span class="pl-smi">any</span><span class="pl-kos">)</span>: <span class="pl-s1">p1</span> is <span class="pl-smi">D</span><span class="pl-kos">;</span>

<span class="pl-k">interface</span> <span class="pl-smi">D</span> <span class="pl-kos">{</span>
    <span class="pl-c1">a</span>: <span class="pl-smi">A</span> <span class="pl-c1">|</span> <span class="pl-smi">B</span>
    <span class="pl-c1">b</span>: <span class="pl-smi">A</span> <span class="pl-c1">|</span> <span class="pl-smi">C</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">let</span> <span class="pl-s1">d</span>: <span class="pl-smi">D</span><span class="pl-kos">;</span>
<span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-en">isA</span><span class="pl-kos">(</span><span class="pl-s1">d</span><span class="pl-kos">.</span><span class="pl-c1">b</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-s1">d</span><span class="pl-kos">.</span><span class="pl-c1">b</span><span class="pl-kos">.</span><span class="pl-c1">propA</span><span class="pl-kos">;</span> <span class="pl-c">//error</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">d</span>: <span class="pl-smi">D</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">d</span><span class="pl-kos">.</span><span class="pl-c1">b</span> <span class="pl-k">instanceof</span> <span class="pl-smi">A</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-s1">d</span><span class="pl-kos">.</span><span class="pl-c1">b</span><span class="pl-kos">.</span><span class="pl-c1">propA</span> <span class="pl-c">// error</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">I'm not sure if there is an easy fix on this problem. We are provided just a symbol when narrowing. That symbol represent the left most expression and then we walk up the if statement. There is no easy way of controlling symbol by symbol on each namespace in a property access expression in the if-statement-body. Because there is no info about the property access expression provided in <code class="notranslate">getTypeOfSymbolAtLocation(symbol: Symbol, node: Node)</code>.</p>
<p dir="auto">I also found that type assertion expressions are also not working in type predicate functions. But I will land a fix on that.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="if (isA(&lt;A&gt;union)) {
    a = union;
}
if (isA(union as A)) {
    a = union;
}"><pre class="notranslate"><span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-en">isA</span><span class="pl-kos">(</span><span class="pl-kos">&lt;</span><span class="pl-smi">A</span><span class="pl-kos">&gt;</span><span class="pl-s1">union</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-s1">a</span> <span class="pl-c1">=</span> <span class="pl-s1">union</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>
<span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-en">isA</span><span class="pl-kos">(</span><span class="pl-s1">union</span> <span class="pl-k">as</span> <span class="pl-smi">A</span><span class="pl-kos">)</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-s1">a</span> <span class="pl-c1">=</span> <span class="pl-s1">union</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>