TypeScript 泛型解析

TypeScript 泛型解析

💡 原文中文,约4600字,阅读约需11分钟。
📝

内容提要

TypeScript 泛型将类型作为参数传入,支持自动推断,并可用 extends 限定类型范围。泛型还能在同一类型定义内绑定多个类型的关系,例如通过 keyof 和映射类型让键与值关联。实战中可用 MyMapArgs 预先映射参数,使 wrapper 函数类型正确,从而避免使用 as any。

🔎

延伸解读

泛型不只是复用:类型联动的关键

文章强调泛型除了复用类型,还能在同一类型定义内绑定多个类型的关系。例如 getProperty 中 Key extends keyof Type 将键与对象类型绑定,确保键必须是对象的属性。映射类型中,[K in MyKey]: Parameters<MyMap[K]> 让每个键的值类型与对应函数参数关联,避免类型信息丢失。这种联动是泛型在复杂类型定义中的核心价值。

实战中的类型绑定陷阱与解法

在 wrapper 函数实战中,直接使用 MyMap 和泛型约束时,TypeScript 无法自动关联键与函数参数类型,导致需要 (fn as any) 绕过检查。文章给出的解法是预先定义 MyMapArgs 接口,显式映射每个键的参数元组,再基于它构造 MyMap。这样 TypeScript 就能理解键与参数的关系,从而移除 as any,获得更安全的类型检查。

映射类型与键重映射的进阶用法

文章展示了通过 as 子句在映射类型中重映射键,例如 Getters 类型将 Person 的属性转换为 get 前缀的方法,并保留原属性类型。这利用了 TypeScript 4.1 的键重映射能力,结合 Capitalize 等工具类型,可以生成更符合实际需求的类型结构。注意 as 重映射要求类型兼容,不能随意转换。

❓

Q&A

TypeScript 泛型是什么?怎么理解?

泛型可以理解成把类型当变量传到类型定义里,就如同参数传到函数一样。例如 function identity<Type>(arg: Type): Type { return arg; },使用 <> 包裹 Type 就能把类型传入泛型函数。

TypeScript 泛型如何自动推断类型?

在使用泛型函数时可以不明确指出 T 的类型,TS 将自动推断 T 的类型。例如 let output = identity("myString"); 此时 output 也是 string。

TypeScript 泛型中 extends 有什么作用?

通过 extends 可以给泛型画个圈,框定它的类型。例如 <T extends Lengthwise> 表明 T 必须是一个有 length 属性的类型,这样就能通过类型检查并访问 length 属性。

TypeScript 泛型如何绑定多个类型的关系?

泛型可以用于类型的联动,T 可以对同一个类型定义内运用到的其他泛型进行绑定。例如 function getProperty<Type, Key extends keyof Type>(obj: Type, key: Key) 中 Key 绑定为 Type 的 key。

TypeScript 映射类型中如何保持键和值的关联?

使用映射类型如 { [K in MyKey]: Parameters<MyMap[K]>; },其中 K 是 MyKey 的 key,并且值必须是 MyMap[K] 的参数,这样就绑定了 Key 和值的固定关系。

在 TypeScript 中如何避免使用 as any 来包装函数?

可以先定义一个 MyMapArgs 接口预先映射参数,再用它构造 MyMap,这样 TS 就能明白键和值参数类型的关系,从而在 wrapper 函数中直接使用 fn.apply(null, arg) 而无需 as any。

🏷️

标签

➡️

继续阅读