simplify the life

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

posted on 2023-04-21 20:09  lessfish  阅读(144)  评论(0)    收藏  举报

导航