本文介绍一些 typescript 中常用的内置类型,以及其可以衍生出的类型。
Partial
Partial 的作用是给某个类型中的属性加上?这个标识,也就是将必须的属性转为可选项。在本类型中首先要理解两个关键词:in
、keyof
。keyof 可以取到一个对象接口的所有 key 值,返回一个 String Literal Types,即字符串字面量类型。
比如:
1 | interface Person { |
而 in 可以遍历联合类型,比如:
1 | type Keys = "name" | "age"; |
然后看下Partial
源码
1 | // node_modules/typescript/lib/lib.es5.d.ts |
意思就是拿到 T 所有的属性名,然后 in 遍历,赋值给 P,最后用 T[P]取得属性的值。比如使用上面的 Person 接口
1 | const hunter: Person = { |
使用 Partial 之后
1 | type PartialPerson = Partial<Person>; |
但是 Partial 有个局限性,只能处理第一层属性,比如:
1 | interface Person { |
如果要处理多层,就需要通过Conditional Types实现更强大的 Partial
1 | export type PowerPartial<T> = { |
Conditional Types
Conditional Types
是 ts2.8 引入的一个条件类型,比如:
1 | type XOrY = T extends U ? X : Y; |
意思就是如果 T 是 U 的子类型,就返回 X,否则返回 Y,甚至可以多个组合
1 | type TypeName<T> = |
Required
1 | type Required<T> = { |
这个类型刚好和 Partial 相反,Partial 是将所有属性改为不必须,Required 是将所有属性改为必须。
其中关键就是-?
,它的作用就是移除?
标识,还可以应用在readonly,比如:
1 | type Readonly<T> = { |
Readonly 是给属性添加readonly
标识,如果改成-readonly
就是移除属性的readonly
标识。比如:
1 | type Mutable<T> = { |
Pick
1 | type Pick<T, K extends keyof T> = { |
如果使用过lodash,就知道这个类型是将子属性取出来,比如:
1 | type NewPerson = Pick<Person, 'name'>; // { name: string; } |
可以看到 NewPerson 中就只有 name 属性了。
Record
将 K 中所有属性值转为 T 类型。
1 | type Record<K extends keyof any, T> = { |
比如:
1 | type T11 = Record<'a' | 'b' | 'c', Person>; // { a: Person; b: Person; c: Person; } |
Exclude
1 | type Exclude<T, U> = T extends U ? never : T; |
顾名思义,就是把 T 中继承于 U 的类型移除,比如:
1 | type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">; // "b" | "d" |
这个类型可以结合 Pick 来使用。当我们要继承某个接口,又需要修改某个属性的类型。比如:
1 | interface Chicken { |
然后我们要继承上面的接口,但是我们的 name 不再是 string 而是 number
1 | interface NewChicken extends Pick<Chicken, 'age' | 'egg'> { |
优化一下,使用下 Exclude
1 | interface NewChicken extends Pick<Chicken, Exclude<keyof Chicken, 'name'>> { |
然后封装成一个单独的类型
1 | type Omit<T, U> = Pick<T, Exclude<keyof T, U>>; |
再次优化
1 | interface NewChicken extends Omit<Chicken, 'name'> { |
ReturnType
1 | type ReturnType<T> = T extends ( |
这个类型是获取方法的返回类型,在Conditional Types
中,我们可以用infer
声明一个类型变量并对它进行使用。这里就是声明一个变量来承载返回值类型。比如:
1 | function TestFn() { |
Extract
1 | type Extract<T, U> = T extends U ? T : never; |
结合实例
1 | type T = Extract<1 | 2, 1 | 3> // -> 1 |
可以得知,extract 的作用是从 T 中提取 U。
ThisType
1 | interface ThisType<T> { } |
可以看到只声明了一个接口,其实这个类型的作用是指定上下文对象类型。
1 | interface Person { |
这样 obj 中的所有方法的上下文对象都成了 Person 这个类型,和下面差不多
1 | const obj = { |
NonNullable
1 | type NonNullable<T> = T extends null | undefined ? never : T; |
这个类型可以用来过滤类型中的 null 及 undefined 类型。
比如:
1 | type T22 = '123' | '222' | null; |
reference
https://wanghx.cn/blog/github/issue13.html
https://zhuanlan.zhihu.com/p/40311981
- 本文链接: https:https://whyour.cn/post/typescript-inner-type.html
- 最后更新于:
- 版权声明: 本博客所有文章除特别声明外,均采用 署名 4.0 国际(CC BY 4.0) 许可协议。转载请注明出处!