title: Can I change the return type based on a parameter
body: <p>I am unsure as to how to formulate my question, so bear with me if the question title looks incorrect to you.</p>
  <pre class="lang-js prettyprint-override"><code>function uselessFunction(value: number): string | number {
      if (value &gt; 5) {
          return &quot;false&quot;
      }
      return 2
  }
  
  const uselessVar1 = uselessFunction(1);
  // type is `string | number`
  // expected would be `number`
  
  const uselessVar2 = uselessFunction(10);
  // type is `string | number`
  // expected would be `string`.
  </code></pre>
  <p>I know about <code>typeguard</code> concept, and how I could use it, but that's not my use-case.</p>
  <pre class="lang-js prettyprint-override"><code>function isString(value: string | number): value is string {
      if (typeof value === &quot;string&quot;) {
          return true
      }
      return false
  }
  
  if (isString(uselessVar1) {
      // uselessVar1 type is `string`.
  }
  
  </code></pre>
  <p>I would like to know if it's possible for typescript to know if <code>uselessVar1</code> is either a <code>string</code> or a <code>number</code> immediatly after the return, and how could I achieve this.</p>
  <p>Also, as to the <code>how</code> is interesting to me, I'd also like to know if it's a bad practice and why.</p>
  <p>If you're more interested in the original use-case...</p>
  <pre class="lang-js prettyprint-override"><code>/** 
   * Takes an input of type &lt;T&gt;[].
   * And returns bins of this list, of length binSize.
   * Example:
   *  
   * makeBinsFromArray([1, 2, 3, 4, 5], 3);
   * // [[1, 2, 3], [4, 5]]
   * 
   * makeBinsFromArray([1, 2, 3, 4, 5, 6, 7], 3);
   * // [[1, 2, 3], [4, 5, 6], [7]]
   * 
   * makeBinsFromArray([1, 2, 3, 4, 5, 6, 7], 3, true);
   * // [[1, 2, 3], [4, 5, 6], [7, undefined, undefined]]
  */
  function makeBinsFromArray&lt;T&gt;(
    value: T[],
    binSize: number,
    fillLast?: boolean
  ): (T | (T | undefined))[][] {
    ...
  }
  
  const result = makeBinsFromArray([1, 2, 3], 2, true);
  // expected type: (T | undefined)[][]
  
  const result = makeBinsFromArray([1, 2, 3], 2);
  // expected type: T[][];
  
  </code></pre>
  <p>Using this function, I want to know if I have a type <code>T[][]</code> or <code>(T | undefined)[][]</code> at compile time, depending on my <code>fillLast</code> argument.</p>