title: Type inference when using complex "isEmpty" check
body: <p>I have the following function which works like <a href="https://github.com/ramda/ramda/blob/master/source/isEmpty.js" rel="nofollow noreferrer">ramdas isEmpty</a>, but tailored to my own needs:</p>
  
  <pre><code>/**
   * Checks if a value is empty.
   * It will return true for the following cases:
   * null, undefined, empty string, empty Set, empty Map, an object without properties.
   * @param input Can be any value.
   * @example
   *
   *     isEmpty([1, 2, 3]); //=&gt; false
   *     isEmpty([]); //=&gt; true
   *
   *     isEmpty(''); //=&gt; true
   *
   *     isEmpty(null); //=&gt; true
   *     isEmpty(undefined); //=&gt; true
   *
   *     isEmpty({}); //=&gt; true
   *
   *     isEmpty(new Set([1, 2, 3])); //=&gt; false
   *     isEmpty(new Set()); //=&gt; true
   *
   *     isEmpty(0); //=&gt; false
   *
   *     isEmpty(new Date()); //=&gt; true
   *     isEmpty(Date.now()); //=&gt; false
   */
  export const isEmpty = (input: any): boolean =&gt; {
    const isMapOrSet = input instanceof Map || input instanceof Set;
    return input === null
      || input === undefined
      || (input instanceof String ? input.length &gt; 0 : false)
      || (isMapOrSet ? input.size === 0 : false)
      || (!isMapOrSet &amp;&amp; input instanceof Object ? Object.keys(input).length === 0 : false);
  };
  </code></pre>
  
  <p>Using this function is pretty straightforward, but I'm unhappy with the <code>boolean</code> return type because TypeScript cannot infer the null checks that this function provides.</p>
  
  <p>For example, the following code is perfectly fine, but TypeScript will complain about a possible null at the <code>someResult[0]</code> call.</p>
  
  <pre><code>const someResult: [] | null = getStuffFromAPI();
  const x = isEmpty(someResult)
  ? {}
  : someResult[0]; // TypeScript will complain about a possible _null_ here.
  </code></pre>
  
  <p>So the question is:
  <strong>How can I improve the function's signature, so that TypeScript can properly infer the return type?</strong></p>
  
  <p>I tried to model a custom return type by utilizing <a href="https://www.typescriptlang.org/docs/handbook/advanced-types.html" rel="nofollow noreferrer">conditional types</a>, but I couldn't figure out how to it correctly.</p>
  
  <p>To make it a 100% clear what I'm searching for, here's some <em>pseudo code</em> (please note that <code>HasNoElements</code> and <code>IsEmpty</code> do not exist in TS):</p>
  
  <pre><code>type IsEmpty&lt;T&gt; =
    T extends null | undefined ? true :
    T extends Map &amp; HasNoElements ? true :
    T extends Set &amp; HasNoElements ? true :
    T extends String &amp; IsEmpty ? true :
    T extends Object &amp; IsEmpty ? true :
    false;
  </code></pre>
  
  <p>Maybe I'm overthinking this, but I'd like to broaden my horizon a bit.</p>