Consider this example:
export function fn(arg: string): void;
export function fn(arg: number): void;
export function fn(arg: any) {
console.log(arg);
}
So, fn
can be called either with a string, or a number.
fn('hello!');
fn(42);
So far, so good.
But then fn
is executed in a different place:
function fn2(arg2: string | number) {
fn(arg2);
}
In this case TypeScript complains:
No overload matches this call. Overload 1 of 2, '(arg: string): void', gave the following error.
Argument of type 'string | number' is not assignable to parameter of type 'string'.
Type 'number' is not assignable to type 'string'. Overload 2 of 2, '(arg: number): void', gave the following error.
Argument of type 'string | number' is not assignable to parameter of type 'number'.
Type 'string' is not assignable to type 'number'.ts(2769)
index.tsx(3, 17): The call would have succeeded against this implementation, but implementation signatures of overloads are not externally visible.
Can someone help me understand what's going on here?
CodePudding user response:
Overloads aren't the same as Union Types. Overloads define 'separate' functions while unions allow you to put different types as arguments.
// fails
function fn2(arg2: string | number) {
fn(arg2); // uses the union type
}
// works
function fn3(arg2: string | number) {
if(typeof arg2 === 'string') {
return fn(arg2); // uses string
}
return fn(arg2); // uses number
}
This means fn2
searches for a function declaration that has an argument of type string|number
while fn3
searches for either a function with type string
or a function with type number
as its first argument.
You should not use any
if you exactly know, which type you want as a function parameter.
See the documentation for Union Types
CodePudding user response:
You can add another overload
export function fn(arg: string): void;
export function fn(arg: number): void;
export function fn(arg: any): void;
export function fn(arg: any) {
console.log(arg);
}
fn('hello!');
fn(42);
function fn2(arg2: string | number) {
fn(arg2);
}