TypeScript泛型是语言最强大的功能之一,也是不熟悉类型语言的开发者最困惑的功能之一。以下是从概念到实际应用的清晰渐进。
泛型解决的问题
没有泛型,你面临选择:为每种类型编写相同逻辑(重复的)、使用any(丢失类型安全),或使用unknown(需要类型转换)。泛型让你编写适用于任何类型的代码,同时在操作过程中保留类型信息。
// 没有泛型——丢失类型信息
function firstItem(arr: any[]): any { return arr[0]; }
const item = firstItem([1, 2, 3]); // item: any — TypeScript不知道它是数字
// 有泛型——类型信息被保留
function firstItem(arr: T[]): T { return arr[0]; }
const item = firstItem([1, 2, 3]); // item: number — TypeScript知道
const str = firstItem(['a', 'b']); // str: string
类型约束
泛型可以使用extends约束以要求特定属性:
interface HasId { id: number; }
function getById(items: T[], id: number): T | undefined {
return items.find(item => item.id === id);
}
// 现在TypeScript知道T有.id——如果你传递没有id的对象会报错
泛型接口和类型
interface ApiResponse {
data: T;
status: number;
message: string;
}
type UserResponse = ApiResponse;
type PostResponse = ApiResponse;
// UserResponse.data是User;PostResponse.data是Post[]
泛型值得用的情况
使用泛型用于:处理集合的工具函数(filter、map、sort)、共享数据结构(树、队列、结果类型)、API响应包装器,以及变化的React组件prop类型。不要使用泛型用于:只处理一种类型的函数、有固定props的组件,或任何有更简单方案明显的情况。过度使用泛型产生技术上正确但比必要更难读的代码。




