1. typeof

2. infer

表示在**extends**条件语句中待推断的类型变量,通常用来获取不确定的类型变量。

T extends U ? X : Y的形式为条件类型(Conditional Types),即,如果类型T能够赋值给类型U,那么该表达式返回类型X,否则返回类型Y

2.1 提取函数的参数类型

  1. type ParamType<T> = T extends (...args: infer P) => any ? P : T;

在这个条件语句T extends (...args: infer P) => any ? P : T中,infer P表示待推断的函数参数类型。

整句表示为:如果T能赋值给(...args: infer P) => any,则结果是(...args: infer P) => any类型中的参数P,否则返回为T

  1. interface User {
  2. name: string;
  3. age: number;
  4. }
  5. type Func = (user: User) => void;
  6. type Param = ParamType<Func>; // Param = User
  7. type AA = ParamType<string>; // string

2.2 提取函数的返回值类型

其实就是TypeScript内置类型ReturnType的实现。

  1. type ReturnType<T> = T extends (...args: any[]) => infer P ? P : any

相比于2.1的示例,ReturnType<T>只是将infer P从参数位置移动到返回值位置,所以此时的P是表示待推断的返回值类型。

  1. type Func = () => User;
  2. type Test = ReturnType<Func>; // Test = User

2.3 提取数组里的元素类型

提取不同类型的数组里的元素类型,使用infer将会变得十分简单。

  1. type Ids = number[];
  2. type Names = string[];
  3. type Unpacked<T> = T extends (infer R)[] ? R : T;
  4. type idType = Unpacked<Ids>; // number
  5. type nameType = Unpacked<Names>; // string

这里T extends (infer R)[] ? R : T的意思是,如果T是某个待推断类型的数组,则返回推断的类型,否则返回T

2.4 提取Promise的返回值类型

假如有如下类型:

  1. type PromiseType<T> = (...args: any[]) => Promise<T>

那么对于符合上面类型的一个方法,如何得知其返回的Promise返回的类型?

譬如对于这么一个返回string类型的Promise

  1. async function stringPromise() {
  2. return "string promise";
  3. }

首先想到的是使用内置的ReturnType来实现:

  1. type stringPromiseReturnType = ReturnType<typeof stringPromise>; // Promise<string>

确实拿到了函数的返回类型,不过是Promise<string>,但我们其实是想要返回里面的string

我们可以继续从Promise<T>中提取出<T>来:

  1. type UnPromisify<T> = T extends PromiseType<infer P> ? P : never;

这样,如果符合PromiseType类型的方法,我们就可以获取其Promise返回的类型值。

  1. async function stringPromise() {
  2. return "string promise";
  3. }
  4. async function numberPromise() {
  5. return 1;
  6. }
  7. interface Person {
  8. name: string;
  9. age: number;
  10. }
  11. async function personPromise() {
  12. return { name: "Wayou", age: 999 } as Person;
  13. }
  14. type extractStringPromise = UnPromisify<typeof stringPromise>; // string
  15. type extractNumberPromise = UnPromisify<typeof numberPromise>; // number
  16. type extractPersonPromise = UnPromisify<typeof personPromise>; // Person

2.5 推断联合类型

  1. type Foo<T> = T extends { a: infer U; b: infer U } ? U : never;
  2. type T10 = Foo<{ a: string; b: string }>; // string
  3. type T11 = Foo<{ a: string; b: number }>; // string | number

同一个类型变量在推断的值有多种情况的时候会推断为联合类型,针对这个特性,很方便的可以将元组转为联合类型。

  1. type ElementOf<T> = T extends (infer R)[] ? R : never;
  2. type TTuple = [string, number];
  3. type Union = ElementOf<TTuple>; // Union 类型为 string | number