<p dir="auto">There is a type that is quite interesting in typescript <code class="notranslate">void | {}</code>, this type has some unique behavior, everything can be assigned to this type, but the compiler does not infer any property for this type unlike for <code class="notranslate">{}</code> that inherits the basic object properties, the difference with <code class="notranslate">{}</code> is subtile but still pretty interesting:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function func1(val: {} ) {
    val.hasOwnProperty('hello'); // no error
}
function func2(val: {} | void) {
    val.hasOwnProperty('hello');  // error:  Property 'hasOwnProperty' does not exist on type 'void | {}'.
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">func1</span><span class="pl-kos">(</span><span class="pl-s1">val</span>: <span class="pl-kos">{</span><span class="pl-kos">}</span> <span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-s1">val</span><span class="pl-kos">.</span><span class="pl-en">hasOwnProperty</span><span class="pl-kos">(</span><span class="pl-s">'hello'</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-c">// no error</span>
<span class="pl-kos">}</span>
<span class="pl-k">function</span> <span class="pl-en">func2</span><span class="pl-kos">(</span><span class="pl-s1">val</span>: <span class="pl-kos">{</span><span class="pl-kos">}</span> <span class="pl-c1">|</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-s1">val</span><span class="pl-kos">.</span><span class="pl-en">hasOwnProperty</span><span class="pl-kos">(</span><span class="pl-s">'hello'</span><span class="pl-kos">)</span><span class="pl-kos">;</span>  <span class="pl-c">// error:  Property 'hasOwnProperty' does not exist on type 'void | {}'.</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">However there is not typeguard for <code class="notranslate">void</code>, it could be interesting to add some type guards for this case:</p>
<ul dir="auto">
<li><code class="notranslate">typeof val !== 'undefined'</code></li>
<li><code class="notranslate">val !== undefined</code></li>
<li><code class="notranslate">val != undefined</code></li>
<li><code class="notranslate">val != null</code></li>
</ul>
<p dir="auto">I think that it should be special <strong>bottom</strong> type with the following properties:</p>
<ul dir="auto">
<li>( T | <strong>bottom</strong> ) = ( <strong>bottom</strong> | T ) = T   — <strong>bottom</strong> is unit for type unions;</li>
<li>expression of type <strong>bottom</strong> is assignable to any other type;</li>
<li><strong>bottom</strong> type could be used only as return type of the function (out-only);</li>
<li>if function has return type <strong>bottom</strong> then  all branches of the control flow either throw exceptions or return expression of type <strong>bottom</strong>;</li>
<li>if all branches of the control flow either throw exceptions or return expression of type <strong>bottom</strong> and function has no explicit return type then <strong>bottom</strong> type inferred as the result type;</li>
<li><del>two functional types are not assignable to each other if exactly one of them has return type <strong>bottom</strong></del> (?);</li>
<li><strong>bottom</strong> type can't be used as the actual type parameter for the generic type.</li>
</ul>
<h3 dir="auto">rationale</h3>
<p dir="auto">Let's consider the function that always throws:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function alwaysThrows() {
    throw new Error(&quot;!&quot;);
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">alwaysThrows</span><span class="pl-kos">(</span><span class="pl-kos">)</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">"!"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">and other function that uses it</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function test(a: boolean) {
    return a ? 123 : alwaysThrow();
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">test</span><span class="pl-kos">(</span><span class="pl-s1">a</span>: <span class="pl-smi">boolean</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">return</span> <span class="pl-s1">a</span> ? <span class="pl-c1">123</span> : <span class="pl-en">alwaysThrow</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">We expect that <code class="notranslate">test</code> should have type <code class="notranslate">number</code> instead of <code class="notranslate">( number | void )</code></p>
<p dir="auto">In more sophisticated example that involves Promise type declarations:</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="declare class Promise&lt;T&gt; {
    catch&lt;U&gt;(
        handler: (reason: any) =&gt; U | Promise&lt;U&gt;
    ): Promise&lt;T | U&gt;;  // Note the union here (!)
    then&lt;U&gt;(
        fulfilled?: (result: T) =&gt; U | Promise&lt;U&gt;,
        rejected?: (reason: any) =&gt; U | Promise&lt;U&gt;
    ): Promise&lt;U&gt;
}"><pre class="notranslate"><span class="pl-k">declare</span> <span class="pl-k">class</span> <span class="pl-smi">Promise</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-c1">catch</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">handler</span>: <span class="pl-kos">(</span><span class="pl-s1">reason</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-c1">|</span> <span class="pl-smi">Promise</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-smi">Promise</span><span class="pl-kos">&lt;</span><span class="pl-smi">T</span> <span class="pl-c1">|</span> <span class="pl-smi">U</span><span class="pl-kos">&gt;</span><span class="pl-kos">;</span>  <span class="pl-c">// Note the union here (!)</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">fulfilled</span>?: <span class="pl-kos">(</span><span class="pl-s1">result</span>: <span class="pl-smi">T</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-smi">U</span> <span class="pl-c1">|</span> <span class="pl-smi">Promise</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">rejected</span>?: <span class="pl-kos">(</span><span class="pl-s1">reason</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-c1">|</span> <span class="pl-smi">Promise</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-smi">Promise</span><span class="pl-kos">&lt;</span><span class="pl-smi">U</span><span class="pl-kos">&gt;</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">We expect that</p>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="promiseOfString.catch(function(e) {
   throw new BusinessError(e);
});"><pre class="notranslate"><span class="pl-s1">promiseOfString</span><span class="pl-kos">.</span><span class="pl-en">catch</span><span class="pl-kos">(</span><span class="pl-k">function</span><span class="pl-kos">(</span><span class="pl-s1">e</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
   <span class="pl-k">throw</span> <span class="pl-k">new</span> <span class="pl-v">BusinessError</span><span class="pl-kos">(</span><span class="pl-s1">e</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<p dir="auto">should have the type of <code class="notranslate">Promise&lt;string&gt;</code>  instead of  <code class="notranslate">Promise&lt;string | void&gt;</code>.</p>
<p dir="auto">See <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="68933329" data-permission-text="Title is private" data-url="https://github.com/petkaantonov/bluebird/issues/589" data-hovercard-type="issue" data-hovercard-url="/petkaantonov/bluebird/issues/589/hovercard?comment_id=99979305&amp;comment_type=issue_comment" href="https://github.com/petkaantonov/bluebird/issues/589#issuecomment-99979305">petkaantonov/bluebird#589 (comment)</a></p>
<p dir="auto">Possible explicit annotation that function always throws is using <strong>undefined</strong> as the type</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="function alwaysThrows(): undefined {
    throw new Error(&quot;!&quot;);
}"><pre class="notranslate"><span class="pl-k">function</span> <span class="pl-en">alwaysThrows</span><span class="pl-kos">(</span><span class="pl-kos">)</span>: <span class="pl-c1">undefined</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">"!"</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span></pre></div>