infer是在 typescript 2.8 中新增的关键字。
一、简单的示例
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。
二、extends
infer 关键词常在条件类型中和 extends 关键词一同出现,表示将要推断的类型,作为类型变量可以在三元表达式的 True 部分引用。
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
type func = () => number;
type variable = string;
type funcReturnType = ReturnType<func>; // funcReturnType 类型为 number
type varReturnType = ReturnType<variable>; // varReturnType 类型为 string
在这个例子中,infer R代表待推断的返回值类型,如果T是一个函数,则返回函数的返回值,否则返回any
三、解包
infer 的作用不止是推断返回值,还可以解包
type Unpacked<T> = T extends (infer R)[] ? R : T;
type Ids = number[];
type Names = string[];
type idType = Unpacked<Ids>; // idType 类型为 number
type nameType = Unpacked<Names>; // nameType 类型为string
这样就能简单获取数组里的元素类型
四、推断联合类型
type Foo<T> = T extends { a: infer U; b: infer U } ? U : never;
type T10 = Foo<{ a: string; b: string }>; // T10类型为 string
type T11 = Foo<{ a: string; b: number }>; // T11类型为 string | number
同一个类型变量在推断的值有多种情况的时候会推断为联合类型,针对这个特性,很方便的可以将元组转为联合类型
type ElementOf<T> = T extends (infer R)[] ? R : never;
type TTuple = [string, number];
type Union = ElementOf<TTuple>; // Union 类型为 string | number
简单的记录一下,后面用到再深入了解。