TypeScript泛型是类型系统最强大的特性之一——也是最常被误解的之一。许多开发人员要么避免泛型(改为写`any`),要么用他们不需要的泛型过度工程化。本指南专注于在日常TypeScript代码中出现的实用模式以及它们解决的具体问题。
泛型是什么以及何时需要它们
泛型解决的核心问题:编写在多种类型上一致工作同时保留类型信息的函数。没有泛型:
“`typescript
function identity(value: any): any { return value; }
const result = identity(42); // result: any — 类型信息丢失
“`
有泛型:
“`typescript
function identity
const result = identity(42); // result: number — 类型保留
“`
`T`是一个类型参数——在调用时将被指定(或推断)的类型占位符。何时使用泛型:当你需要一个在类型上一致工作同时保留类型信息的函数或类时;当你正在构建可复用的工具类型时;当函数的返回类型取决于输入类型时。何时不使用泛型:当`unknown`(类型检查但未知)或联合类型(如`string | number`)就足够时;当类型总是相同时。过度泛型是一种常见的反模式——如果一个函数只接受并返回字符串,它就不应该是泛型的。最重要的泛型模式:泛型函数(如上所示)、泛型接口、泛型类型别名和泛型约束。
实用泛型模式
泛型约束(`extends`):约束泛型可以是什么类型。最常见的模式:
“`typescript
function getProperty
return obj[key];
}
const user = { name: “Alice”, age: 30 };
const name = getProperty(user, “name”); // string — 自动补全有效
// getProperty(user, “email”) 在编译时会报错
“`
这是`keyof`模式——TypeScript表达”T类型某个键的字符串”的方式。返回类型`T[K]`是”索引访问类型”——TypeScript将其解析为实际的属性类型。用于数据结构的泛型接口:
“`typescript
interface ApiResponse
data: T;
status: number;
message: string;
}
type UserResponse = ApiResponse
type PostsResponse = ApiResponse
“`
这种模式在API客户端代码中无处不在。`Awaited
“`typescript
type IsArray
type A = IsArray
type B = IsArray
“`
条件类型中的`infer`关键字:
“`typescript
type UnpackPromise
type Unpacked = UnpackPromise
type Direct = UnpackPromise
“`
`infer U`表示”如果T是一个Promise,将包装的类型推断到U中”。这就是`Awaited
“`typescript
type Partial
type Readonly
type Stringify
“`
内置工具类型(`Partial




