title: Typescript Overloading Error
body: <p>I have come across an error related to function overloading in typescript and have written this minimal example to reproduce the error.</p>
  
  <pre><code>interface XComplex {
    value: X
  }
  type X = string | XComplex
  
  interface YComplex {
    value: Y
  }
  type Y = string | YComplex
  
  function transform(v: string): string
  function transform(v: XComplex): YComplex
  function transform(x: X): Y {
    if (typeof x === "string") {
      return x
    }
  
    const xValue: X = x.value
  
    return {
      value: transform(xValue), // &lt;---- **ERROR**
    }
  }
  
  // **ERROR**
  // [ts]
  // Argument of type 'X' is not assignable to parameter of type 'XComplex'.
  //   Type 'string' is not assignable to type 'XComplex'.
  </code></pre>
  
  <p>The error does not occur if I remove the overloaded signatures but then the following use cases would not work.</p>
  
  <pre><code>// WITH OVERLOADING
  const yString1: string = transform('hello')
  const yComplex1: YComplex = transform({ value: 'xValue'})
  // WITHOUT OVERLOADING
  const yString2: Y = transform('hello')
  const yComplex2: Y = transform({ value: 'xValue'})
  </code></pre>
  
  <p>In the error it seems that the "Argument of type 'X'" is xValue which is "not assignable to parameter of type 'XComplex'" which would be the parameter of transform. But transform takes a parameter of type X so I'm not sure what I am doing wrong.</p>
  
  <hr>
  
  <p>EDIT 1:</p>
  
  <p>It seems that if I add an extra overloaded signature it works as intended.</p>
  
  <pre><code>function transform(v: string): string
  function transform(v: XComplex): YComplex
  function transform(v: X): Y &lt;--- EXTRA OVERLOADED SIGNATURE
  function transform(x: X): Y { ... }
  </code></pre>
  
  <p>Now I'm just not sure why this is necessary or how to have understood this from the error message.</p>
  
  <hr>
  
  <p>EDIT 2:</p>
  
  <p>After thinking about this more, I guess since xValue is of type X, typescript could not possibly know whether it is a string or an XComplex and so none of</p>
  
  <pre><code>function transform(v: string): string
  function transform(v: XComplex): YComplex
  </code></pre>
  
  <p>would match. I assume then that typescript is just going through the signatures one by one until it reaches the last one and realises none match so it just outputs "Argument of type 'X' is not assignable to parameter of type 'XComplex'." referring to the last signature. An error stating that no overloaded signatures match seems like it would be more helpful. </p>
  
  <p>This explains why the kind of 'catch all' case</p>
  
  <pre><code>function transform(v: X): Y &lt;--- EXTRA OVERLOADED SIGNATURE
  </code></pre>
  
  <p>is necessary.</p>