Skip to content

泛型是 TypeScript 类型系统里最核心、也最考验功力的概念——它让类型"参数化",写一次代码就能适配多种类型。这篇把泛型从头讲清楚:为什么要泛型、泛型函数/接口/约束、以及最常用的工具类型。

一、解决什么问题:不写死类型

没有泛型,想写一个"返回原值"的函数,要么用 any(丢类型),要么为每种类型各写一个:

typescript
// 用 any:丢失类型信息,调用方拿不到类型提示
function identity(x: any): any { return x; }
const r = identity("hello");   // r 是 any,没有类型提示

// 泛型:类型参数化,返回类型和入参类型一致
function identity<T>(x: T): T { return x; }
const r1 = identity("hello");  // r1 是 string(自动推断)
const r2 = identity(18);       // r2 是 number

泛型 = 类型的"参数"<T> 声明一个类型参数,调用时自动推断(或手动指定)。

二、泛型函数与泛型接口

typescript
// 泛型函数:多个类型参数
function pair<K, V>(key: K, value: V): [K, V] {
    return [key, value];
}
pair("age", 18);        // [string, number]

// 泛型接口:最常见的是"响应包装"
interface ApiResponse<T> {
    code: number;
    message: string;
    data: T;
}
// 不同接口复用同一个包装
const userResp: ApiResponse<User> = { code: 0, message: "ok", data: { name: "BinMaker" } };
const listResp: ApiResponse<User[]> = { code: 0, message: "ok", data: [...] };

泛型接口是后端返回类型、状态管理里的标配——一个 ApiResponse<T> 包所有返回结构。

三、泛型约束:限制类型参数

有时要限制 T 必须有某些属性,用 extends 约束:

typescript
// 约束 T 必须有 length 属性
function getLen<T extends { length: number }>(x: T): number {
    return x.length;
}
getLen("hello");     // ✓ string 有 length
getLen([1, 2, 3]);   // ✓ 数组有 length
// getLen(18);       // ❌ number 没有 length,编译报错

<T extends 约束> 的语义:T 必须是约束类型的子类型(满足约束的结构)。

四、工具类型:TS 内置的泛型利器

TS 内置了几个最常用的工具类型,都是泛型的应用:

typescript
interface User {
    name: string;
    age: number;
    email: string;
}

// Partial:所有字段变可选(常用于更新场景)
type PartialUser = Partial<User>;   // { name?; age?; email?; }

// Pick:挑出部分字段
type NameOnly = Pick<User, "name">;  // { name: string }

// Omit:排除部分字段(常用!去掉密码等敏感字段)
type SafeUser = Omit<User, "email">; // { name; age; }

// Record:构造"键值对"类型
type UserMap = Record<string, User>; // { [key: string]: User }

Omit 特别常用:接口返回时排除敏感字段(如 Omit<User, "password">),一行搞定。

小结

  • 泛型 = 类型参数化,写一次适配多种类型
  • 泛型函数/接口让类型"可复用",ApiResponse<T> 是经典场景
  • <T extends 约束> 限制类型参数必须有某结构
  • 工具类型:Partial(全可选)、Pick(挑字段)、Omit(排除字段,常用)、Record(键值对)

泛型是 TS 高级类型(条件类型、映射类型、类型推断)的基础,理解了泛型,看那些高级类型就顺了。想回顾 TS 类型系统的其他基础,看《TypeScript 类型系统》。