title: In Typescript, why function overloading order matters only when the overloaded function is passed as a parameter?
body: <p>When a function is overloaded and passed to a function as parameter, it seems to not maintain the overloading, only the last definition is chosen.</p>
  
  <p>I verified that the definition order matters and created a minimal example: <a href="https://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABBAhgGzQHgKqIKYAeUeYAJgM6JwBGAVntADSIBqAfABQoAOMAXIg4BKRAF42iAIK8czds24oATigC25AdiECACkriqY5PJnaIA3gChEN5AnJREqvFAAWcUmMQ8YwgNzWtkouIEpIYHgA7oh6BkZ4HBzB5CLiFoG2ts5uHhyKKurMHHhKSszJ3KkSVpm1QSFhiBUBdTYAvkIZiB0BbZaWUACe3HhSMthyEqKC+WoaiBPI6GjUKBAA1gLFpQLmbeV45NwCLFWIAG5wMKRnl9cBlgD0AFTPiADKMADmYChQoaMOABGETPR6WUCQWAIby8ACyLncpDyyjmu2uAjAIFU1BK+yWGFWGy2JSUu3xFV2aDgaEx2NxSg6YgkdxuAlZAReb0+Pz+AMEACZQeDIdB4EgfAicsjUIS1ptBKTyQcjlSaXScXjblc2RcdQFRdCJfDEbkurN1AB5JQAYWWRIV5gxiCxmsZiAAPoJtmSLBTDscLNTaS76VrmXrrkJmF1ZSt5QB+Ek7P0qwPmYMahlMtKsywiGq2GDAQRxh0FrqZMvyjh7ZgZ9WIIECgDMABYAKwANgA7D0un1MsXBEMRnASxbyNa7XKNmJRNMAOSG8WLiutRCT6f2mt1oON5vt7t9oQtWx9PpPR6IACSJfI31+-2CghBiFxwDgL4fvOfgKFiBuCQgGuEYiBgSggHDKMpJflet4loMcAgE4cDnKMP5PvyHAAR+X4YY+fIvsCIhAUgbhgRBGBwJEeCkJYED2I4SheHGiRnJKpqkPWzotv28EACqgZQYEgA+YBfIgmFEYCb4oGQ4GUJEX7rDAEmILRGCWJx0q1s6h74sIEZ7KegnCYpiBiWpknSX+goiPJnhgcpSiqepmloNpJq6UZaQmQEQA" rel="nofollow noreferrer">Playground link</a></p>
  
  <pre><code>function call&lt;U extends object, V&gt;(method: Api&lt;U, V&gt;, params: U): Promise&lt;V&gt; {
      return new Promise((res) =&gt; {
          method(params, (err, resp) =&gt; {
              return resp;
          })
      });
  }
  
  type Api&lt;U, V&gt; = (params: U, callback: (err: {}, resp: V) =&gt; void) =&gt; void;
  
  /** Signature (1) */
  function apiMethod(params: {id: number}, callback: (err: {}, resp: {lol: number}) =&gt; void): void;
  /** Signature (2) */
  function apiMethod(callback: (err: {}, resp: {lol: number}) =&gt; void): void;
  function apiMethod(
      paramsOrCallback: {id: number} | ((err: {}, resp: {lol: number}) =&gt; void), 
      callback?: (err: {}, resp: {lol: number}) =&gt; void
  ) {
      if (callback) {
          callback({}, {lol: 1234567});
      }
      if (typeof paramsOrCallback === 'function') {
          paramsOrCallback({}, {lol: 1234567});
      }
  }
  
  // If signature (1) before signature (2) then this is a type error
  // If you move signature (2) before signature (1) then this is allowed
  const r = call(apiMethod, {id: 3});
  
  // This is using signature (1) and is working well
  apiMethod({id: 123}, () =&gt; {});
  // This is using signature (2) and is working well
  apiMethod(() =&gt; {});
  </code></pre>
  
  <p>I was expecting this example to compile and work correctly independently of the order of signature (1) and signature (2). </p>
  
  <p>Seems that the TS compiler decides which function definition at the time in which the function is passed and for some reason the last definition is always chosen.</p>
  
  <p>I would like to have clarification about why this is happening (and suggested reading material about internals of function overloading) and how to remediate enriching the type of the function <code>call</code> in order to make it work independently of the signature (1) and (2) order.</p>