返回

在 TypeScript 中巧妙运用 Infer Extends:全面解析与实用案例

前端

简介

TypeScript 作为一门强大的类型化编程语言,提供了丰富的类型系统,其中 infer extends 机制是一个非常有用的功能,它允许我们从类型中提取部分类型,并将其存储为一个新的类型变量。这种模式匹配的方式在各种场景下都有着广泛的应用,例如从元组中提取最后一个元素的类型、推断函数的返回值类型,甚至是字符串处理。

理解 Infer Extends

infer extends 的语法格式如下:

type NewType = infer T extends SomeType

其中 NewType 是新的类型变量,它将存储从 SomeType 中提取的一部分类型。 extends 指定了模式匹配的规则,我们可以在其中指定具体的类型模式。

例如,以下代码从一个元组类型中提取最后一个元素的类型:

type LastElement<T extends [any, ...any[]]> = infer U extends T[number]

在这个例子中,模式匹配规则指定了 T 必须是一个元组,并且其最后一个元素的类型存储在 U 中。

实用案例

元组类型

  • 提取最后一个元素的类型:
type LastElement<T extends [any, ...any[]]> = infer U extends T[number]
  • 提取前面 N 个元素的类型:
type FirstNElements<T extends [any, ...any[]], N extends number> = infer U extends T[number][]

函数类型

  • 推断函数的返回值类型:
type ReturnType<T extends (...args: any[]) => any> = infer R extends T extends (...args: any[]) => infer R ? R : any
  • 检查函数是否返回 Promise:
type IsPromise<T extends (...args: any[]) => any> = infer R extends T extends (...args: any[]) => Promise<infer R> ? true : false

字符串处理

  • 提取字符串的一部分:
type Substring<T extends string, Start extends number, End extends number> = infer S extends T extends `${string.substring(0, Start)}${infer S}${string.substring(End)}` ? S : never
  • 替换字符串的一部分:
type ReplaceSubstring<T extends string, From extends string, To extends string> = infer S extends T extends `${string.substring(0, From.length)}${infer S}${string.substring(From.length + To.length)}` ? `${string.substring(0, From.length)}${To}${S}` : never

其他用法

  • 类型条件约束:
type IsArray<T> = infer U extends T[] ? true : false
  • 条件类型:
type Condition<T extends true, TrueType, FalseType> = infer U extends T ? TrueType : FalseType

总结

TypeScript 的 infer extends 机制为我们提供了强大的类型推断能力,它使我们能够从各种类型中提取部分类型,从而实现更灵活和动态的类型化编程。通过上述实用案例,我们展示了 infer extends 在元组类型、函数类型、字符串处理以及其他场景中的应用,帮助开发者充分利用 TypeScript 的类型系统,编写出更高效、更可维护的代码。