extends 泛型约束
我们一般使用extends来继承接口或者类,但是extends还可以用来泛型约束
function getCnames<T extends { name: string }>(entities: T[]):string[] {
return entities.map(entity => entity.cname)
}
比如,以上代码对传入的参数进行了约束,传入的参数必须要有name
这个属性,否则就会出错
条件类型与高阶类型
extends
还有一大用途就是用来判断一个类型是不是可以分配给另一个类型,这在写高级类型的时候非常有用,举个例子
type Lihua = {
name: string;
}
type Xiaoming = {
name: string;
}
type Bool = Lihua extends Xiaoming ? 'yes' : 'no'; // Bool => 'yes'
Lihua
和Xiaoming
这两个类型都有name
这个属性,而且类型是相同的,所以最后的结果是yes
type Human = {
name: string;
occupation: string;
}
type Duck = {
name: string;
}
type Bool = Duck extends Human ? 'yes' : 'no'; // Bool => 'no'
而这段代码中,Duck
中并不存在Human
中相关属性,所以Duck
不满足约束条件,所以最后返回的是no
当我们给
Human
加上一个occupation
属性,发现此时Bool
是'no'
,这是因为 Duck 没有类型为string
的occupation
属性,类型Duck
不满足类型Human
的类型约束。因此,A extends B
,是指类型A
可以分配给
类型B
,而不是说类型A是类型B的子集,理解extends在类型三元表达式里的用法非常重要。
type A1 = 'x' extends 'x' ? string : number; // string
type A2 = 'x' | 'y' extends 'x' ? string : number; // number
type P<T> = T extends 'x' ? string : number;
type A3 = P<'x' | 'y'> // string | number
P是带参数T的泛型类型,其表达式和A1,A2的形式完全相同,A3是泛型类型P传入参数
'x' | 'y'
得到的类型对于使用extends关键字的条件类型(即上面的三元表达式类型),如果extends前面的参数是一个泛型类型,当传入该参数的是联合类型,则使用
分配律
计算最终的结果。分配律是指,将联合类型的联合项拆成单项
,分别代入条件类型,然后将每个单项代入得到的结果再联合起来,得到最终的判断结果。