在 TypeScript 中,infer 关键字通常与条件类型一起使用,在条件类型中定义泛型里面推断出来的类型参数,从而可以在后续的类型计算中使用这个类型。
1、用法
(1) 条件类型语法
T extends U ? X : Y
上面使用 extends 关键字判断类型 T 是否可以被安全地视为类型 U 的一个子类型,如果是那么条件类型的结果就是 X,否则结果就是 Y。
(2) 条件类型使用 infer
例子1:
type F<T> = T extends Array<infer K> ? K : T;
上面例子中,T extends Array<infer K> 表示如果参数 T 是一个数组,那么就将该数组的成员类型推断出来并定义为 K,并且条件类型的结果为 K;如果参数 T 不是数组类型,那么条件类型的结果为 T。
下面使用 F<T> 类型:
// string
type S = F<string[]>;
// boolean
type B = F<boolean>;
上面代码中:
F<string[]> 传入的类型参数(T)是 string[],TypeScript 推断出数组成员类型是 string,即 infer K 中的 K 代表的是类型 string,所以最终返回的是类型 string。
F<boolean> 传入的类型参数是 boolean,它不是数组,所以直接返回自身。
如果不用 infer 定义类型参数,那么就要传入两个类型参数,很是麻烦。
type F<T, K> = T extends Array<K> ? K : T;
例子2:
type PromiseFun<T> = T extends (...args: infer P) => infer K
? (...args: P) => Promise<K>
: T;
上面例子中,如果 T 是函数,就返回这个函数的 Promise 版本,否则原样返回。infer P 表示该函数的参数类型为 P,infer K 表示该函数的返回值类型为 K。
例子3:
type NiceType<T> = T extends {
x: infer U;
y: infer V;
}
? [U, V]
: never;
// 用法示例
type NT1 = NiceType<{ a: string; b: number }>;
// never
type NT2 = NiceType<{ x: string; y: number }>;
// [string, number]
上面示例中,infer 提取了参数对象的属性 x 和属性 y 的类型。
例子4:
type Str = "s-b";
type Bar = Str extends `s-${infer rest}` ? rest : never;
// 相当于
type Bar = "b"
上面例子中,rest 是从模板字符串提取的类型参数,这里是 'b'。