I have come across an error related to function overloading in typescript and have written this minimal example to reproduce the error.
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), // <---- **ERROR**
}
}
// **ERROR**
// [ts]
// Argument of type 'X' is not assignable to parameter of type 'XComplex'.
// Type 'string' is not assignable to type 'XComplex'.
The error does not occur if I remove the overloaded signatures but then the following use cases would not work.
// 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'})
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.
EDIT 1:
It seems that if I add an extra overloaded signature it works as intended.
function transform(v: string): string
function transform(v: XComplex): YComplex
function transform(v: X): Y <--- EXTRA OVERLOADED SIGNATURE
function transform(x: X): Y { ... }
Now I'm just not sure why this is necessary or how to have understood this from the error message.
EDIT 2:
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
function transform(v: string): string
function transform(v: XComplex): YComplex
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.
This explains why the kind of 'catch all' case
function transform(v: X): Y <--- EXTRA OVERLOADED SIGNATURE
is necessary.