1、简介
当函数的返回值的类型依赖于参数类型,想要表达出这种类型关系就需要用到泛型。泛型的特点就是带有“类型参数"。
function getFirst<T>(arr: T[]): T {
return arr[0]
}
<T>表示类型参数为T,用一对尖括号<>包裹。
当调用getFirst([1,2,3])时,ts可以直接根据函数定义推断出来类型参数T为number类型
但有些场景需要显示给出
function comb<T>(arr1: T[], arr2: T[]): T[] {
return arr1.concat(arr2);
}
如果直接调用comb([1,2,3],['4', '5','6']),没有明确写出T的类型,那么ts会根据参数[1,2,3]推断出T的类型为number,因此会报错。
这里需要指明类型参数T的类型为comb<number|string>([1, 2], ['a', 'b']),这样就能✅类型检查
1.1 类型参数的默认值
function getFirst<T = string>(
arr:T[]
):T {
return arr[0];
}
类型参数T默认为string类型,
getFirst([1, 2, 3]),T的类型为number
1.2 类型参数的约束条件
类型参数并不是无限制的,对于传入的类型可以设置约束条件
function comp<Type>(a:Type, b:Type) {
if (a.length >= b.length) {
return a;
}
return b;
}
Type 有一个隐藏的约束条件:它必须存在length属性。如果不满足这个条件,就会报错。
function comp<T extends { length: number }>(
a: T,
b: T
) {
if (a.length >= b.length) {
return a;
}
return b;
}
T extends { length: number }就是一个约束条件,表示类型参数T必须是满足{ length: number }
T extends U 表示T是U的子类型
2、泛型的应用
函数泛型的写法
function id<T>(arg:T):T {
return arg;
}
接口的泛型写法
interface Box<Type> {
contents: Type;
}
let box:Box<string>;
类的泛型写法
class Pair<K, V> {
key: K;
value: V;
}
类型别名的泛型写法
type Nullable<T> = T | undefined | null;
数组的泛型写法
let arr:Array<number> = [1, 2, 3];