<p dir="auto">Spec 3.4 says:</p>
<blockquote>
<p dir="auto">Union types are reduced to the smallest possible set of constituent types using these rules</p>
</blockquote>
<p dir="auto">But in compiler they are not reduced in case of inferring type parameters in function invocations. For example:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="var o = {};

// According to spec, type of p should be reduced to {}
function f&lt;T&gt;(p: T | typeof o): T 
{
    var t: T;
    var temp = t || o; // here union type is reduced, and it is really {}
    return null;
}

// Another function where type of p is really {}. According to spec, it should be equal to f, shouldn't it?
function f2&lt;T&gt;(p: typeof o): T 
{
    return null;
}

// But really they are different
var e = f(5); // number
var e2 = f2(5); // {}"><pre class="notranslate"><span class="pl-k">var</span> <span class="pl-s1">o</span> <span class="pl-c1">=</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">;</span>

<span class="pl-c">// According to spec, type of p should be reduced to {}</span>
<span class="pl-k">function</span> <span class="pl-en">f</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">p</span>: <span class="pl-smi">T</span> <span class="pl-c1">|</span> <span class="pl-k">typeof</span> <span class="pl-s1">o</span><span class="pl-kos">)</span>: <span class="pl-smi">T</span> 
<span class="pl-kos">{</span>
    <span class="pl-k">var</span> <span class="pl-s1">t</span>: <span class="pl-smi">T</span><span class="pl-kos">;</span>
    <span class="pl-k">var</span> <span class="pl-s1">temp</span> <span class="pl-c1">=</span> <span class="pl-s1">t</span> <span class="pl-c1">||</span> <span class="pl-s1">o</span><span class="pl-kos">;</span> <span class="pl-c">// here union type is reduced, and it is really {}</span>
    <span class="pl-k">return</span> <span class="pl-c1">null</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-c">// Another function where type of p is really {}. According to spec, it should be equal to f, shouldn't it?</span>
<span class="pl-k">function</span> <span class="pl-en">f2</span><span class="pl-c1">&lt;</span><span class="pl-smi">T</span><span class="pl-c1">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">p</span>: <span class="pl-k">typeof</span> <span class="pl-s1">o</span><span class="pl-kos">)</span>: <span class="pl-smi">T</span> 
<span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-c1">null</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-c">// But really they are different</span>
<span class="pl-k">var</span> <span class="pl-s1">e</span> <span class="pl-c1">=</span> <span class="pl-en">f</span><span class="pl-kos">(</span><span class="pl-c1">5</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// number</span>
<span class="pl-k">var</span> <span class="pl-s1">e2</span> <span class="pl-c1">=</span> <span class="pl-en">f2</span><span class="pl-kos">(</span><span class="pl-c1">5</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// {}</span></pre></div>
<p dir="auto">Could you please clarify, when union type are really reduced and when they are not.</p>
<p dir="auto"><strong>TypeScript Version:</strong> 1.8.10</p>
<p dir="auto">So when I use the <code class="notranslate">--declaration</code> cli flag on <code class="notranslate">tsc</code>, or its corollary in <code class="notranslate">tsconfig.json</code>, I found that the definitions it produces have the <strong><code class="notranslate">public</code></strong> keyword stripped out. I couldn't find anything about why this might be on google, but did see that when there is no modifier present, <strong><code class="notranslate">public</code></strong> is assumed. Looking around at some popular type definitions, they also seem to lack the keyword. So, obviously its not needed. But, if I write it in my source, why not carry that over to the definition? It doesn't seem to affect the inference engines of the editors I quickly tested. So even if this is negligible, why not let it through? I like my code to be <del>statically</del> <strong><em>brutally</em></strong>-typed. I think it makes my intentions clearer as to what I would intend be exposed as an API to consuming developers. I see some potential for how this could be used by an IDE to rank symbols during autocomplete, and even more importantly, for auto generating documentation.</p>
<p dir="auto">Is there some reason behind this? pragmatically/legacy/or otherwise? It seems like it would be a trivial fix. Interested to hear everyone's thoughts!</p>
<p dir="auto"><strong>Code</strong><br>
<em>file:</em>    <kbd>Foo.ts</kbd></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class Foo {
    public memberPublic: string;
    public methodPublic(): number {
        // ...
    }
    private memberPrivate: string;
    private methodPrivate(): number {
        // ...
    }
    protected memberProtected: string;
    protected methodProtected(): number {
        // ...
    }
}
export default Foo;"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-smi">Foo</span> <span class="pl-kos">{</span>
    <span class="pl-k">public</span> <span class="pl-c1">memberPublic</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
    <span class="pl-k">public</span> <span class="pl-en">methodPublic</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-c">// ...</span>
    <span class="pl-kos">}</span>
    <span class="pl-k">private</span> <span class="pl-c1">memberPrivate</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
    <span class="pl-k">private</span> <span class="pl-en">methodPrivate</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-c">// ...</span>
    <span class="pl-kos">}</span>
    <span class="pl-k">protected</span> <span class="pl-c1">memberProtected</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
    <span class="pl-k">protected</span> <span class="pl-en">methodProtected</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-c">// ...</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>
<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-smi">Foo</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><em>file:</em>    <kbd>tsconfig.json</kbd></p>
<div class="highlight highlight-source-json notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="{
  &quot;compilerOptions&quot;: { /* same result when I use */
    &quot;target&quot;: &quot;es2015&quot;, /* es5 */
    &quot;module&quot;: &quot;es2015&quot;, /* commonjs */
    &quot;moduleResolution&quot;: &quot;node&quot;,
    &quot;sourceMap&quot;: true,
    &quot;declaration&quot;: true,
    &quot;noImplicitAny&quot;: true,
    &quot;noLib&quot;: false,
    &quot;outDir&quot;: &quot;lib&quot;,
    &quot;allowSyntheticDefaultImports&quot;: true,
    &quot;removeComments&quot;: false,
  },
  &quot;exclude&quot;: [
    &quot;typings/browser.d.ts&quot;,
    &quot;typings/browser&quot;,
    &quot;node_modules&quot;,
    &quot;lib&quot;
  ]
}
"><pre class="notranslate">{
  <span class="pl-ent">"compilerOptions"</span>: { <span class="pl-ii">/* same result when I use */</span>
    <span class="pl-ent">"target"</span>: <span class="pl-s"><span class="pl-pds">"</span>es2015<span class="pl-pds">"</span></span>, <span class="pl-ii">/* es5 */</span>
    <span class="pl-ent">"module"</span>: <span class="pl-s"><span class="pl-pds">"</span>es2015<span class="pl-pds">"</span></span>, <span class="pl-ii">/* commonjs */</span>
    <span class="pl-ent">"moduleResolution"</span>: <span class="pl-s"><span class="pl-pds">"</span>node<span class="pl-pds">"</span></span>,
    <span class="pl-ent">"sourceMap"</span>: <span class="pl-c1">true</span>,
    <span class="pl-ent">"declaration"</span>: <span class="pl-c1">true</span>,
    <span class="pl-ent">"noImplicitAny"</span>: <span class="pl-c1">true</span>,
    <span class="pl-ent">"noLib"</span>: <span class="pl-c1">false</span>,
    <span class="pl-ent">"outDir"</span>: <span class="pl-s"><span class="pl-pds">"</span>lib<span class="pl-pds">"</span></span>,
    <span class="pl-ent">"allowSyntheticDefaultImports"</span>: <span class="pl-c1">true</span>,
    <span class="pl-ent">"removeComments"</span>: <span class="pl-c1">false</span>,
  },
  <span class="pl-ent">"exclude"</span>: [
    <span class="pl-s"><span class="pl-pds">"</span>typings/browser.d.ts<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>typings/browser<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>node_modules<span class="pl-pds">"</span></span>,
    <span class="pl-s"><span class="pl-pds">"</span>lib<span class="pl-pds">"</span></span>
  ]
}
</pre></div>
<p dir="auto"><strong>Expected behavior:</strong><br>
<em>file:</em>    <kbd>Foo.d.ts</kbd></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="declare class Foo {
    public memberPublic: string;
    public methodPublic(): number;

    private memberPrivate: string;
    private methodPrivate(): number;

    protected memberProtected: string;
    protected methodProtected(): number;
}
export default Foo;"><pre class="notranslate"><span class="pl-k">declare</span> <span class="pl-k">class</span> <span class="pl-smi">Foo</span> <span class="pl-kos">{</span>
    <span class="pl-k">public</span> <span class="pl-c1">memberPublic</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
    <span class="pl-k">public</span> <span class="pl-c1">methodPublic</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">private</span> <span class="pl-c1">memberPrivate</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
    <span class="pl-k">private</span> <span class="pl-c1">methodPrivate</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">protected</span> <span class="pl-c1">memberProtected</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
    <span class="pl-k">protected</span> <span class="pl-c1">methodProtected</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-kos">}</span>
<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-smi">Foo</span><span class="pl-kos">;</span></pre></div>
<p dir="auto"><strong>Actual behavior:</strong><br>
<em>file:</em>    <kbd>Foo.d.ts</kbd></p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="declare class Foo {
    memberPublic: string;
    methodPublic(): number;

    private memberPrivate: string;
    private methodPrivate(): number;

    protected memberProtected: string;
    protected methodProtected(): number;
}
export default Foo;"><pre class="notranslate"><span class="pl-k">declare</span> <span class="pl-k">class</span> <span class="pl-smi">Foo</span> <span class="pl-kos">{</span>
    <span class="pl-c1">memberPublic</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
    <span class="pl-c1">methodPublic</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">private</span> <span class="pl-c1">memberPrivate</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
    <span class="pl-k">private</span> <span class="pl-c1">methodPrivate</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">protected</span> <span class="pl-c1">memberProtected</span>: <span class="pl-smi">string</span><span class="pl-kos">;</span>
    <span class="pl-k">protected</span> <span class="pl-c1">methodProtected</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-kos">}</span>
<span class="pl-k">export</span> <span class="pl-k">default</span> <span class="pl-smi">Foo</span><span class="pl-kos">;</span></pre></div>