TypeScript 的关键字 infer 有什么作用?

2024-08-26 15:21:11 472
TypeScript 的 `infer` 关键字 是在条件类型中使用的一种特殊关键字,允许你在条件类型中推断出某个类型。`infer` 通常与 `extends` 条件类型一起使用,用来从某个复杂的类型中提取子类型或者推导出更具体的类型。

基本语法

infer 通常与条件类型结合使用,其语法形式如下:

T extends SomeType<infer U> ? X : Y
  • T extends SomeType<infer U>:表示在类型 T 满足 SomeType 条件的前提下,推断出 U 类型。
  • X:当条件为真时,返回的类型(通常使用 U)。
  • Y:当条件为假时,返回的类型。

示例 1: 从数组类型中推断元素类型

infer 常用于从复杂类型中提取出元素的类型。下面是一个从数组类型中提取出元素类型的示例。

type ElementType<T> = T extends (infer U)[] ? U : T;

type StringArray = ElementType<string[]>;  // string
type NumberArray = ElementType<number[]>;  // number
type NotArray = ElementType<string>;       // string

解释:

  • T extends (infer U)[] 表示检查 T 是否是一个数组类型,如果是数组类型,则推断出 U 为数组元素的类型。
  • StringArray 推断为 string,因为 string[] 是字符串数组,元素类型是 string
  • NotArray 不是数组类型,因此返回原始类型 string

示例 2: 从函数类型中推断参数或返回值类型

你可以使用 infer 从函数类型中提取出参数或返回值的类型。

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;

type MyFunction = (a: number, b: string) => boolean;
type Result = ReturnType<MyFunction>;  // boolean

解释:

  • T extends (...args: any[]) => infer R 用来检查 T 是否是一个函数类型,如果是,则推断出 R 为返回值的类型。
  • Result 推断为 boolean,因为 MyFunction 的返回值类型是 boolean

示例 3: 推断元组的第一个元素类型

使用 infer 可以从元组类型中提取出第一个元素的类型。

type First<T> = T extends [infer U, ...any[]] ? U : never;

type Tuple1 = [number, string, boolean];
type FirstElement = First<Tuple1>;  // number

解释:

  • T extends [infer U, ...any[]] 用来检查 T 是否是一个元组类型,并推断出 U 为元组的第一个元素的类型。
  • FirstElement 推断为 number,因为 Tuple1 的第一个元素类型是 number

示例 4: 推断联合类型中的具体类型

infer 还可以与联合类型结合,提取出联合类型中的具体类型。

type InferType<T> = T extends { a: infer A; b: infer B } ? A & B : never;

type ExampleType = { a: string; b: number };
type ResultType = InferType<ExampleType>;  // string & number

解释:

  • T extends { a: infer A; b: infer B } 表示检查 T 是否具有 ab 属性,并推断出 AB 的类型。
  • ResultType 推断为 string & number,表示 ab 的交集类型。

总结

infer 关键字 是 TypeScript 中用于条件类型的一种工具,主要用于从复杂类型中推断或提取类型信息。通过 infer,你可以在类型层面进行灵活的类型推导,使得条件类型的应用更加强大和灵活。它通常用于泛型、函数类型和数组类型等场景。