Suppose there is such a function, how would you declare its type?
function add(a,b){
return a+b;
}
add
function may have two situations:
- The parameter
a、b
is ofnumber
, and the return value is of typenumber
- The parameter
a、b
is ofstring
, and the return value is of typestring
Can it be solved by using function overloading?
First, you may implement the overload declaration add
function add(a: string, b: string): string;
function add(a: number, b: number): number;
function add(a: any, b: any) {
return a + b;
}
add(1, 2); //function add(a: number, b: number): number
add('x', 'y'); //function add(a: string, b: string): string
This method is obviously good, but there is a small problem: when the number|string
parameter type is 06176873cbb325, an unexpected type error will occur.
let a:string|number;
add(a,a);
/*
第 1 个重载(共 2 个),“(a: string, b: string): string”,出现以下错误。
类型“string | number”的参数不能赋给类型“string”的参数。
不能将类型“number”分配给类型“string”。
第 2 个重载(共 2 个),“(a: number, b: number): number”,出现以下错误。
类型“string | number”的参数不能赋给类型“number”的参数。
不能将类型“string”分配给类型“number”。
*/
This is because when we use function overloading, TypeScript uses these overloads to compare one by one until the appropriate type overload is matched. But obviously, we declare the variable type two overloaded in, number
and string
are associated with number|string
does not match, so there are a type of error.
How about using generics?
Then, you might also think of using generics to declare types in order to build a common pattern.
function add<T extends number | string>(a: T, b: T): T;
function add(a: any, b: any) {
return a + b;
}
const a:number = 0;
const b:string='str';
add(a, a);//function add<number>(a: number, b: number): number
add(b, b);//function add<string>(a: string, b: string): string
This method looks good, but also has a small problem: When an incoming literal type of parameters, the type of the parameter will be considered and the parameters same value type. E.g:
add(1,2);//function add<1 | 2>(a: 1 | 2, b: 1 | 2): 1 | 2
Parameters 1
of type
is 1
, and non number
, just as we declare type T=1|2
; as a function of the type of declaration generic T necessary to meet the first argument 1
, but also to meet the second argument 2
, So the type of T becomes 1|2
; similarly, if the incoming variable a、b
does not have explicit type declaration number
and string
, this problem will also occur.
Condition type might be better
In fact, using conditional types when such functions need to be overloaded may have better results.
function add<T extends number | string>(
a: T,
b: T
): T extends number ? number : string;
function add(a: any, b: any) {
return a + b;
}
add(1,2);//function add<1 | 2>(a: 1 | 2, b: 1 | 2): number
let a:number|string;
add(a, a);//function add<string | number>(a: string | number, b: string | number): string | number
In this way, the type of the parameter is first obtained through the generic method, and then the condition type is used for judgment, so as to obtain the correct type.
This method is more complicated to write than the previous two methods, but the type will be more accurate. When a function requires type overloading, consider using conditional types to implement it.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。