Description
π Search Terms
map overload overloaded
π Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about overloading
β― Playground Link
Bug report
This code fails to compile:
function foo(x: number): number;
function foo(x: string): string;
function foo(x) {
return x;
}
const arr: number[] = [1,2,3].map(foo);
with the following errors:
Type 'string[]' is not assignable to type 'number[]'.
Type 'string' is not assignable to type 'number'.
and
Argument of type '{ (x: number): number; (x: string): string; }' is not assignable to parameter of type '(value: number, index: number, array: number[]) => string'.
Type 'number' is not assignable to type 'string'.
This doesn't make much sense, since there's no reason (so far as I can see) that TypeScript shouldn't be able to recognise that foo
will only be passed numbers as arguments when called via [1,2,3].map(foo);
, and that therefore (per the two overload signatures) will only return numbers, not strings. Furthermore, it can in fact infer this if you use an arrow function instead of passing foo
as an argument directly, i.e. this compiles just fine:
function foo(x: number): number;
function foo(x: string): string;
function foo(x) {
return x;
}
const arr: number[] = [1,2,3].map(x => foo(x));
Especially odd is that the original code also compiles fine if you swap the order in which the overloads are defined:
function foo(x: string): string;
function foo(x: number): number;
function foo(x) {
return x;
}
const arr: number[] = [1,2,3].map(foo);
The explanation appears to me to be that posited by #55840 - that, when an overloaded function is passed as a parameter to a function like Array.map
, TypeScript simply (and arbitrarily, and incorrectly) treats its final overload signature as the signature of the function. It should instead infer from context which overload signature is applicable, as it successfully does if you wrap the call in an arrow function.
#55840 was closed as a dupe of #47571, which was closed as having been completed, and indeed the specific example given in that issue no longer seems to reproduce the bug (so I guess that something got changed to fix at least that case), but the underlying bug doesn't seem to have truly been fixed since the trivial example I give at the start of this issue still reproduces it.