Skip to Content

面试导航 - 程序员面试题库大全 | 前端后端面试真题 | 面试

TypeScript 中的 infer 关键字用于条件类型中,用于推断一个类型。这在处理复杂类型时非常有用,可以帮助我们提取或转换类型。

基本用法

infer 关键字只能在条件类型中使用,通常与泛型和 extends 关键字一起使用。它的语法如下:

type Moment<T> = T extends infer U ? U : never;

这里 T extends infer U 意味着我们试图推断类型 T 并将其赋值给 U。如果类型推断成功,那么 U 就是我们推断出的类型。

接下来我们可以用它来推断不同的类型,这里有几个例子:

type Moment<T> = T extends infer U ? U : never; type StringType = Moment<string>; // string type NumberType = Moment<number>; // number type UnionType = Moment<string | number>; // string | number interface User { name: string; age: number; } type UserType = Moment<User>; // User

在这些例子中,Moment<T> 实际上只是返回了 T 的类型,不进行任何转换或处理。这主要是用来演示条件类型和类型推断的基本用法。

常见示例

提取函数返回类型;

假设我们有一个函数类型,我们想要提取这个函数的返回类型,可以这样做:

type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : never; type ExampleFunction = (x: number, y: string) => boolean; type ReturnTypeOfExampleFunction = GetReturnType<ExampleFunction>; // boolean

在上面的这些代码中:

  1. T extends (...args: any[]) => infer R: 这部分检查类型 T 是否是一个函数类型。(…args: any[]) 表示该函数可以接受任意数量的参数。
  2. infer R: 如果 T 是一个函数类型,那么 infer R 将推断出函数的返回值类型,并将其赋给类型变量 R。
  3. ? R : never: 如果 T 是一个函数类型,则返回推断出的返回值类型 R;否则返回 never 类型。

提取数组元素类型

我们还可以使用 infer 来提取数组元素的类型:

type GetArrayElementType<T> = T extends (infer U)[] ? U : never; type Moment = string[]; type Example1Array = Array<string>; type ElementTypeOfExampleArray = GetArrayElementType<Moment>; // string type ElementTypeOfExample1Array = GetArrayElementType<Example1Array>; //string

在这里,我们使用 T extends (infer U)[] 来推断数组元素的类型 U。其中 T 是 string[],U 是 string[] 中的是 string。

string[] extends (infer U)[ ]

值得注意的是,infer 声明仅在条件类型的 extends 子句中才允许使用,并且 infer 声明的类型变量只有在 true 分支中可用。

进阶示例

提取 Promise 的值类型

如果我们有一个 Promise 类型,我们可以提取其解析后的值类型:

type GetPromiseValueType<T> = T extends Promise<infer U> ? U : never; // 示例 type ExamplePromise = Promise<number>; type ValueTypeOfExamplePromise = GetPromiseValueType<ExamplePromise>; // number

在上面的这些代码中:

  1. T extends Promise<infer U>:这部分检查类型 T 是否是一个 Promise 类型。

  2. infer U:如果 T 是一个 Promise 类型,那么 infer U 将推断出 Promise 的值的类型,并将其赋给类型变量 U。

  3. ? U : never:如果 T 是一个 Promise 类型,则返回推断出的值的类型 U;否则返回 never 类型。

提取函数参数类型

有时我们需要获取一个函数的参数类型。可以使用 infer 来实现:

type GetParameters<T> = T extends (...args: infer P) => any ? P : never; type ExampleFunction = (a: number, b: string) => void; type Params = GetParameters<ExampleFunction>; // [number, string]

在上面的这些代码中:

  1. T extends (...args: infer P) => any:这部分检查类型 T 是否是一个函数类型。

  2. infer P:如果 T 是一个函数类型,那么 infer P 将推断出函数的参数类型,并将其赋给类型变量 P。

  3. ? P : never:如果 T 是一个函数类型,则返回推断出的参数类型 P;否则返回 never 类型。

提取构造函数参数类型

我们还可以使用 infer 来提取类构造函数的参数类型:

type ConstructorParameters<T> = T extends new (...args: infer P) => any ? P : never; class ExampleClass { constructor( public a: number, public b: string, ) {} } type Params = ConstructorParameters<typeof ExampleClass>; // [number, string]

条件类型中的复杂推断

假设我们需要在条件类型中使用复杂的推断逻辑:

type IsArray<T> = T extends (infer U)[] ? U : never; type IsFunction<T> = T extends (...args: any[]) => infer R ? R : never; type ExtractType<T> = T extends any[] ? IsArray<T> : T extends (...args: any[]) => any ? IsFunction<T> : T; // 示例 type ArrayType = ExtractType<string[]>; // string type FunctionReturnType = ExtractType<() => number>; // number type DefaultType = ExtractType<boolean>; // boolean

在这段代码中,如下:

type ExtractType<T> = T extends any[] ? IsArray<T> : T extends (...args: any[]) => any ? IsFunction<T> : T;
  1. T extends any[] ? IsArray<T> :如果 T 是一个数组类型,则返回 IsArray<T>,即数组元素的类型。

  2. T extends (...args: any[]) => any ? IsFunction<T>: 如果 T 是一个函数类型,则返回 IsFunction<T>,即函数的返回值类型。

  3. T:如果 T 既不是数组类型也不是函数类型,则返回 T 本身。

总结

infer 关键字用于条件类型中,以从其他类型中推断出一个新的类型变量。它允许在类型检查时提取和使用特定的子类型或属性,从而增强类型系统的表达能力和灵活性。简单来说,infer 可以帮助从复杂类型中自动提取出所需的部分类型。

最后更新于:
Copyright © 2025Moment版权所有粤ICP备2025376666