天天看点

Ts extends 泛型约束extends 泛型约束

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前面的参数是一个泛型类型,当传入该参数的是联合类型,则使用

分配律

计算最终的结果。分配律是指,

将联合类型的联合项拆成单项

,分别代入条件类型,然后将每个单项代入得到的结果再联合起来,得到最终的判断结果。

继续阅读