本博客 hjy-xh,转载请申明出处
extends
关键字在TS中有多种用法,单独使用时,常见有以下几种情况
- 继承/拓展
- 约束
- 条件判断
继承/扩展
单个/多个接口
这种用法和类的继承相似,看个🌰
1 | interface Animal { |
也支持多重继承
1 | interface Blackdog extends Animal, Dog { |
扩展类的接口
除了上面的常见用法,接口还可以继承类的私有成员和受保护成员,而不仅仅是公共成员
1 | class Animal { |
小结
- 一个接口可以继承/扩展一个或多个现有接口
- 一个接口也可以继承/扩展一个类。如果该类包含私有或受保护成员,则该接口只能由该类或其子类实现
约束
此处说的约束,一般指泛型约束,即对泛型的类型进行约束控制
在编写方法的时候,可能会需要对参数的类型做一些限制,比方说入参有一个length
属性
1 | // 没有约束 |
条件判断
和三目表达式类似,看看官网的示例和说明
1 | SomeType extends OtherType ? TrueType : FalseType; |
When the type on the left of the
extends
is assignable to the one on the right, then you’ll get the type in the first branch (the “true” branch); otherwise you’ll get the type in the latter branch (the “false” branch).
如果extends前面的类型能够赋值给extends后面的类型,那么表达式判断为真,否则为假
常规使用
1 | interface A1 { |
A1,A2两个接口,满足A2的接口一定可以满足A1,所以条件为真,A的类型取string
结合泛型使用
1 | type A1 = 'x' extends 'x' ? string : number; // string |
A1、A2的结果也就是常规的用法,很容易得出结果,但是A3结合了泛型,这里有一个Distributive Conditional Types
的概念
When conditional types act on a generic type, they become distributive when given a union type
如果extends前面的参数是一个泛型类型,当传入该参数的是联合类型,则使用分配律计算最终的结果。分配律是指,将联合类型的联合项拆成单项,分别代入条件类型,然后将每个单项代入得到的结果再联合起来,得到最终的判断结果。
以上面的A3为例,进行推导
P
1 | P<'x' | 'y'> => P<'x'> | P<'y'> |
然后将每一项代入得到的结果联合起来,得到string | number
满足两个要点即可适用分配律:第一,参数是泛型类型,第二,代入参数的是联合类型
特殊的never
1 | // never是所有类型的子类型 |
never被认为是空的联合类型,也就是说,没有联合项的联合类型,所以还是满足上面的分配律,然而因为没有联合项可以分配,所以P<T>
的表达式其实根本就没有执行,所以A2的定义也就类似于永远没有返回的函数一样,是never类型的
防止条件判断中的分配
1 | type P<T> = [T] extends ['x'] ? string : number; |
在条件判断类型的定义中,将泛型参数使用[]
括起来,即可阻断条件判断类型的分配,此时,传入参数T的类型将被当做一个整体,不再分配