infer 关键字的引入,使得 TypeScript 的类型系统更加强大和灵活,能够更好地满足开发人员的需求。例如,在处理泛型类型或条件类型时,infer 关键字可以用来捕获类型的某些特征,并在类型推导时使用这些特征来实现更加精确的类型推导。以下是使用场景
1、从泛型类型中,提取类型变量
TypeScript 中泛型类型允许我们编写通用的类型,可以接受任何类型作为其类型参数。infer 关键字可以用于从泛型类型中提取类型参数,并将其用于另一个类型。
示例1:
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
function add(a: number, b: number) {
return a + b;
}
type AddReturnType = ReturnType<typeof add>; // AddReturnType 将推断为 number 类型
ReturnType 类型接受一个泛型参数 T,该参数可以是一个函数类型。使用 infer 关键字,我们可以从函数类型 T 中推断出它的返回类型并将其命名为 R。 如果 T 不是一个函数类型,则 ReturnType 类型返回 never。
定义了一个名为 add 的函数,并使用 typeof 操作符获取其类型。定义了一个名为 AddReturnType 的类型变量,该变量使用 ReturnType 类型并传入 add 函数类型作为泛型参数。AddReturnType 变量将自动推断为 number 类型,因为 add 函数返回一个数字类型。
示例2:
typescriptCopy code
type Last<T extends any[]> = T extends [...infer _, infer U] ? U : never;
type Example1 = Last<[1, 2, 3]>; // Example1 将推断为 number 类型,并且值为 3
type Example2 = Last<[string, boolean, number]>; // Example2 将推断为 number 类型,并且值为 number
定义了一个名为 Last 的类型,该类型接受一个类型参数 T,该参数必须是一个元组类型。然后,我们使用 extends 关键字将 T 与一个新的元组类型 [...infer _, infer U] 进行比较。
这个新的元组类型中使用了 infer 关键字来表示原始元组类型中的所有元素和新元素 U,并使用 _ 来表示我们不关心的元素。 如果 T 是一个元组类型,则它必须与这个新的元组类型匹配,才能使用 U 类型变量进行推断。否则,Last 类型返回 never。
2、从函数参数中提取类型
我们可以使用 Parameters 类型获取函数的参数类型数组。然而,有时候我们需要从函数参数中提取特定类型的参数。这时,就可以使用 infer 关键字。
示例:
type FirstParameter<T> = T extends (a: infer P, ...args: any[]) => any ? P : never;
function greet(name: string, age: number) {
console.log(`Hello, ${name}! You are ${age} years old.`);
}
type NameType = FirstParameter<typeof greet>; // NameType 将推断为 string 类型
在上面的示例中,FirstParameter 类型接受一个泛型参数 T,该参数必须是一个函数类型。使用 infer 关键字,我们从函数类型 T 中推断出它的第一个参数类型,并将其命名为 P。最终,NameType 变量将自动推断为 string 类型,因为 greet 函数的第一个参数是一个字符串类型。