1. typeof
2. infer
表示在**extends**条件语句中待推断的类型变量,通常用来获取不确定的类型变量。
T extends U ? X : Y的形式为条件类型(Conditional Types),即,如果类型T能够赋值给类型U,那么该表达式返回类型X,否则返回类型Y。
2.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。
interface User {name: string;age: number;}type Func = (user: User) => void;type Param = ParamType<Func>; // Param = Usertype AA = ParamType<string>; // string
2.2 提取函数的返回值类型
其实就是TypeScript内置类型ReturnType的实现。
type ReturnType<T> = T extends (...args: any[]) => infer P ? P : any
相比于2.1的示例,ReturnType<T>只是将infer P从参数位置移动到返回值位置,所以此时的P是表示待推断的返回值类型。
type Func = () => User;type Test = ReturnType<Func>; // Test = User
2.3 提取数组里的元素类型
提取不同类型的数组里的元素类型,使用infer将会变得十分简单。
type Ids = number[];type Names = string[];type Unpacked<T> = T extends (infer R)[] ? R : T;type idType = Unpacked<Ids>; // numbertype nameType = Unpacked<Names>; // string
这里T extends (infer R)[] ? R : T的意思是,如果T是某个待推断类型的数组,则返回推断的类型,否则返回T。
2.4 提取Promise的返回值类型
假如有如下类型:
type PromiseType<T> = (...args: any[]) => Promise<T>
那么对于符合上面类型的一个方法,如何得知其返回的Promise返回的类型?
譬如对于这么一个返回string类型的Promise:
async function stringPromise() {return "string promise";}
首先想到的是使用内置的ReturnType来实现:
type stringPromiseReturnType = ReturnType<typeof stringPromise>; // Promise<string>
确实拿到了函数的返回类型,不过是Promise<string>,但我们其实是想要返回里面的string。
我们可以继续从Promise<T>中提取出<T>来:
type UnPromisify<T> = T extends PromiseType<infer P> ? P : never;
这样,如果符合PromiseType类型的方法,我们就可以获取其Promise返回的类型值。
async function stringPromise() {return "string promise";}async function numberPromise() {return 1;}interface Person {name: string;age: number;}async function personPromise() {return { name: "Wayou", age: 999 } as Person;}type extractStringPromise = UnPromisify<typeof stringPromise>; // stringtype extractNumberPromise = UnPromisify<typeof numberPromise>; // numbertype extractPersonPromise = UnPromisify<typeof personPromise>; // Person
2.5 推断联合类型
type Foo<T> = T extends { a: infer U; b: infer U } ? U : never;type T10 = Foo<{ a: string; b: string }>; // stringtype T11 = Foo<{ a: string; b: number }>; // string | number
同一个类型变量在推断的值有多种情况的时候会推断为联合类型,针对这个特性,很方便的可以将元组转为联合类型。
type ElementOf<T> = T extends (infer R)[] ? R : never;type TTuple = [string, number];type Union = ElementOf<TTuple>; // Union 类型为 string | number
