🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] > 在 VSCode 中 Ctrl + 点击关键字,进入 `<My Projects></node_modules/typescript/lib/lib.es5.d.ts` 查看到相关的高级类型(type)实现 # 工具类型(utility types) 这些 TypeScript 预置的工具类型,在全局都是可用的。 ## `Partial<T>` ## `Readonly<T>` 将传入的属性变为只读选项: ```js type Readonly<T> = { readonly [P in keyof T]: T[P] }; ``` ## `Record<K,T>` ## `Pick<T,K>` ## `Omit<T,K>` 使用 Pick 和 Exclude 组合实现: ```js type Omit<T, K extends keyof T> = Pick<T, K Exclude<keyof T, K>> ``` 首先这个`K extends keyof T`说明这个类型值必须为 T 类型属性的子集,`Exclude` 的效果就是寻找在 keyof T 中有,但在 K 类型中没有的成员,这样就将剩余的类型过滤了出来,再去应用 `Pick`,就实现了 `Omit`。 示例: ```js type Foo = Omit<{name: string, age: number}, 'name'> // -> { age: number } ``` ## `Exclude<T,U>` 与`Extract`刚好相反,基于条件类型和`never`实现: ```js type Exclude<T, U> = T extends U ? never : T; ``` 示例: ```js type T = Exclude<1 | 2, 1 | 3> // -> 2 ``` 很轻松地得出结果 `2` 根据代码和示例我们可以推断出 Exclude 的作用是从 T 中找出 U 中没有的元素,换种更加贴近语义的说法其实就是从 T 中排除 U * [`Extract<T,U>`](https://socode.pro/?docspath=handbook%2Futility-types&docscode=typescript#extracttu) ## `NonNullable<T>` ## `Parameters<T>` ## `ConstructorParameters<T>` ## `ReturnType<T>` 获取函数类型的返回类型: ``` type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any; ``` 示例: ``` const foo = (x: number): Array<number> => { return [x]; }; type fn = ReturnType<typeof foo>; ``` ## `InstanceType<T>` 获取构造函数类型的返回类型: ``` type InstanceType<T extends new (...args: any) => any> = T extends new (...args: any) => infer R ? R : any; ``` 示例: ```js class C { x = 0; y =0 ; } type T200 = InstanceType<typeof C> ``` ## `Required<T>` 构造一个包含`T`集合的所有属性为`required`的类型: ``` type Required<T> = { [P in keyof T]-?: T[P]; }; ``` 示例: ``` interface Props { a?: number; b?: string; }; const obj: Props = { a: 5 }; // OK const obj2: Required<Props> = { a: 5 }; // Error: property 'b' missing ``` ## `ThisParameterType` ## `OmitThisParameter` ## `ThisType<T>` `ThisType<T>` 在`lib.es5.d.ts`实现中是空的。它是编译器将`this`指向另一个对象的标记。[this playground](https://www.typescriptlang.org/play?#code/G4QwTgBCAO0KwQLwQHYFMDuEBqBXNAFAN4BQEEaANgFwQDkAxDNALRx0A0ZEAJiAC4hapcuQC2aAM6SQAczS06ACSqUA9jnwA6AFaSAhHW4BfLuLT8AFmp6Th3cmDTA0YSWgCyUmfNoAzXBQAY34ASzUUCAIASggRUXIrUMktCWk5NCQIJJS0nzQtSWhKUP4COjporScXN0IqnTVQlHLKhwhjExJjaJISfgBPaEyAeQAjHTQQgBEpILBQ6H41MAAeaY4IDwA+LPiqWkl+BZRZM14BEAB+WmmAbm4JKxtJG62IADIIABVLZO+hmh1p8tts7hAAPQQn6AiBqPz0HJ0CDNCBPay2FGSCDTEEeboPEg8KaUcCZIIRI6aBTUgDClOOuBCK0Jg2GdIZYCZy0gyHi6Aw602OwIxMkQVo40mMzmCyWKyFoOitzx3SAA): ```js interface ThisType { } // ThisType<T> 是空的 ``` 通过`ThisType`,我们可以在这个特定位置声明`this`的类型。 上面代码的对象描述符是这样的: ```js type ObjectDescriptor<Data, Methods> = { el?: string; data?: Data; methods?: Methods & ThisType<Data & Methods>;}; ``` 它告诉TypeScript,在所有的`methods` 函数中,这可以访问类型`Data`和`Methods`中的字段。 Vue 的简约版本是这样的: ```js declare const Vue: VueConstructor;type VueConstructor = { new<D, M>(desc: ObjectDescriptor<D, M>): D & M) ``` > [工具类型](https://www.typescriptlang.org/docs/handbook/utility-types.html) # 动手实现题 1. 实现一个 ts 的工具函数 `GetOnlyFnProps<T>` ,提取泛型类型 T 中字段类型是函数的工具函数,其中 T 属于一个对象。 ```js type GetOnlyFnKeys<T extends object> = {  [Key in keyof T]: T[K] extends Function ? K : never } type GetOnlyFnProps<T extends object> = {  [K in GetOnlyFnKeys<T>]: T[K] } ``` 2. 实现一个 ts 的工具函数 `UnGenericPromise<T>` ,提取 Promise 中的泛型类型。 ```js type UnGenericPromise<T extends Promise<any>> = T extends Promise<infer U> ? U : never ``` # 工具库 当然了,社区也是有很多类似的工具类型,可在 npm 上搜索... * [utility-types](https://github.com/piotrwitek/utility-types) # 参考 > [TypeScript 高级用法详解](https://juejin.im/post/6844904021300346887) > [bilibili-TypeScript Masterclass](https://www.bilibili.com/video/BV157411f7Fo?p=8)