Typescript Function Overload Caveat
The signature of the implementation is not visible from the outside, and TypeScript can only resolve a function call to a single overload
Number of parameters doesn’t match signature:
function makeDate(timestamp: number): Date; // overload signature
function makeDate(m: number, d: number, y: number): Date; // overload signature
function makeDate(mOrTimestamp: number, d?: number, y?: number): Date {
if (d !== undefined && y !== undefined) {
return new Date(y, mOrTimestamp, d);
} else {
return new Date(mOrTimestamp);
}
}
const d1 = makeDate(12345678);
console.log(d1); // 1970-01-01T03:25:45.678Z
const d2 = makeDate(5, 5, 5);
console.log(d2); // 1905-06-05T00:00:00.000Z
const d3 = makeDate(1, 3); // Error: No overload expects 2 arguments, but overloads do exist that expect either 1 or 3 arguments.Parameter type isn’t compatible with signature
function len(s: string): number;
function len(arr: any[]): number;
function len(x: any) {
return x.length;
}
len(""); // OK
len([0]); // OK
len(Math.random() > 0.5 ? "hello" : [0]); // No overload matches this call. Overload 1 of 2, '(s: string): number', gave the following error. Argument of type 'number[] | "hello"' is not assignable to parameter of type 'string'. Type 'number[]' is not assignable to type 'string'. Overload 2 of 2, '(arr: any[]): number', gave the following error. Argument of type 'number[] | "hello"' is not assignable to parameter of type 'any[]'. Type 'string' is not assignable to type 'any[]'.Because both overloads have the same argument count and same return type, we can instead write a non-overloaded version of the function:
function len(x: any[] | string) {
return x.length;
}This is much better! Callers can invoke this with either sort of value, and as an added bonus, we don’t have to figure out a correct implementation signature.