extends
extends
接口继承
interface Person {
name: string
age: number
}
interface Man extends Person {
height: number
}
此时 Man 自动继承了 Person 下的 name 和 age
泛型约束
实现 Pick:
interface Animal {
name: string
age: number
sex: 'f' | 'm'
}
// 此时 K 是有约束的,不然就应该报错
type MyPick<T, K extends keyof T> = {
[key in K]: T[key]
}
type Dog = MyPick<Animal, 'name' | 'age'>
type Cat = MyPick<Animal, 'name' | 'age2'> // 报错
这里关于 keyof 岔开去一点,keyof 可以获取一个 interface 的所有 key,但是对于几个 interface 呢?比如想获取 interface A 和 B 中的所有 key,或者想获取 A 和 B 中都有的 key 呢?
type Foo = {
a: string
b: number
}
type Bar = {
a: string
c: boolean
}
type A = keyof (Foo & Bar) // "a" | "b" | "c"
type B = keyof (Foo | Bar) // "a"
条件类型
A extends B ? 'Y': 'N'
它的意思是 类型 A 可以分配给类型 B(我个人的理解是,A 可以看成是 B 类型的衍生物,A 比 B 更具象,在某种意义上 A 是 B 的子集)
interface Person {
name: string
age: number
}
interface Man extends Person {
height: number
}
type a = Man extends Person ? true : false // true。Man 继承自 Person,Man 当然也是 Person,所以 Man 可以分配给 Person
type res1 = true extends boolean ? true : false // true
type res2 = 'name' extends 'name' | 'age' ? true : false // true
type res3 = [1, 2, 3] extends { length: number } ? true : false // true
type res4 = [1, 2, 3] extends Array<number> ? true : false // true
分配条件类型
type P<T> = T extends 'x' ? string : number
type A2 = P<'x' | 'y'> // string | number
当 T 为泛型时,且传入该泛型的是一个联合类型,那么该联合类型中的每一个类型都要进行上述操作,最终返回上述操作结果组成的新联合类型
extends 关键字左侧的是一个泛型,且传入泛型的必须是联合类型,其他类型如交叉类型是没有分配效果的
注意:只有 T extends xxx 这种模式,T 才有分配效果。所以如果要保留原来的 T,可以增加泛型变量 K(type P<T, K=T>,然后还是让 T 去 extends)
如果左侧不是泛型,直接传入一个联合类型,是没有分配效果的,只是一个简单的条件判断:
type A1 = 'x' | 'y' extends 'x' ? string : number // number
更多可以参考 此文
Exclude 就是用这个特性来实现的
type Result = Exclude<'a' | 'b' | 'c', 'a'> // "b" | "c"
type MyExclude<T, U> = T extends U ? never : T
几个有趣的例子:
type A = Exclude<boolean, false> // true(这里是因为 boolean 其实是 `true | false` 的别称)
type B = Exclude<string | 'a' | 'b', 'a'> // string
type C = Exclude<string | 'a' | 'b', string> // never
其实是因为:
type A = string | 'a' // string
遍历联合类型
T extends T ? XXX : never
类型拼接
比较有意思的是,ts 里的类型居然还能拼接,像字符串一样
type name = 'fish'
type A = 'hellofish' extends `hello${name}` ? true : false // true
type name = 'fish' | 'chloe'
type A = 'hellofish' extends `hello${name}` ? true : false // true
浙公网安备 33010602011771号