TypeScript类型编程中的extends和infer示例解析

作者:青柠

时间:2026-10-30

浏览:640

本文详细解析TypeScript类型编程中extends和infer的核心用法。通过条件判断、参数约束及局部变量声明等示例,展示如何利用extends限制类型范围,以及利用infer提取复杂类型中的子类型。文章还涵盖了ReturnType和Parameters等内置工具类型的实现原理,帮助开发者掌握高级类型定义技巧。

文章目录

引文

在初学TypeScript时,type和interface是最常用的类型声明关键字,通常足以应对日常开发需求。然而,当需要构建更复杂的高级类型系统时,仅依靠基础语法往往力不从心。

构建高级类型涉及类型编程的概念,其中两个关键机制至关重要:extends和infer。

extends主要用于约束输入参数的类型以及执行条件判断,而infer则用于声明局部类型变量以进行类型推导。

extends

条件判断

通过一个简单示例来说明其工作原理。

type isOne<T extends number> = T extends 1 ? true : false

单独观察T extends 1 ? true : false部分,其语法结构与JavaScript中的三元表达式类似,但部分开发者可能不清楚这里的extends具体指代什么含义。

表达式T extends 1 ? true : false的含义是:检查传入的类型T是否可以赋值给字面量类型1。如果可以,则返回true;否则返回false。

约束参数类型

沿用上述示例,单独分析T extends number,此处的extends表示限制传入的类型T必须为number类型,否则将引发类型错误。

为何需要这种限制?

因为我们的目标是判断类型T是否能赋值给字面量类型1。如果传入的参数根本就不是number类型,那么后续的赋值判断就失去了意义,因此需要预先约束参数类型。

约束infer推导的局部变量类型

type GetFirst<T extends string[]> = T extends [infer FirstChar, ...infer Rest]
  ? `${FirstChar}`
  : never;
type Res = GetFirst<['1', '2', '3']>;

查看报错信息可知,虽然传入的参数类型被限制为string类型的数组,但infer推导出的局部变量类型实际上是unknown类型,从而导致类型不匹配。

引文

解决该问题有三种方法:

对FirstChar使用extends进行预先过滤。

type GetFirst<T extends string[]> = T extends [infer FirstChar, ...infer Rest]
? FirstChar extends string
  ? `${FirstChar}`
  : never
: never;

将FirstChar与string类型进行交叉运算。

type GetFirst<T extends string[]> = T extends [infer FirstChar, ...infer Rest]
? `${FirstChar & string}`
: never;

使用infer extends语法进行类型转换。

type GetFirst<T extends string[]> = T extends [
infer FirstChar extends string,
...infer Rest
]
? `${FirstChar}`
: never;

infer extends特性在TypeScript 4.7版本中引入,低于该版本的编译器不支持此用法。

类型转换

type StrToNum<T extends string> = T extends `${infer Num extends number}` ? Num : T
type Res = StrToNum<"1">
// ts 4.7时,返回的结果是type Res = number
// ts 4.8及以上, 返回的结果是type Res = 1

infer

继续通过示例进行讲解,以下示例旨在提取被Promise包裹的内部类型。

type PromiseValue<T extends Promise<unknown>> = T extends Promise<infer Value> ? Value : never
type Res = PromiseValue<Promise<string>> // string

绘制一张简图来描述变量类型的提取过程。

引文

注意:infer声明的局部变量仅在条件语句为true的分支中可用。

引文

如果在false分支中尝试使用由infer声明的局部变量,编译器会直接报错,提示找不到该变量。

组合使用

ReturnType

内置工具类型RetureType用于获取函数的返回值类型。

type MyReturnType<T extends (...args: any) => any> 
    = T extends (...args: any) => infer R 
        ? R 
        : any;
type Res = MyReturnType<() => string> // type Res = string

Parameters

内置工具类型Parameters用于获取函数的参数类型。

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

以上便是TypeScript类型编程中关于extends和infer的示例解析,更多TypeScript类型编程中extends和infer的相关资料请继续关注本站其他文章!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章