第6章:泛型
6.5 使用泛型提高代码复用性
1. 泛型的核心价值:代码复用与类型安全
泛型(Generics)是 TypeScript 中实现代码复用的核心工具之一,它允许开发者编写可适应多种类型的组件,而无需重复编写相似的逻辑。泛型的核心优势在于:
- 类型安全:在编译时捕获类型错误,避免运行时问题。
- 减少重复:通过抽象类型逻辑,避免为不同类型编写相同功能的代码。
2. 实际场景中的泛型应用
示例 1:通用数据响应结构
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
// 用户数据响应
const userResponse: ApiResponse<{ id: number; name: string }> = {
data: { id: 1, name: "Alice" },
status: 200,
message: "Success",
};
// 商品数据响应
const productResponse: ApiResponse<{ sku: string; price: number }> = {
data: { sku: "P100", price: 99.99 },
status: 200,
message: "Success",
};
示例 2:通用工具函数
function identity<T>(arg: T): T {
return arg;
}
// 自动推断类型为 string
const result1 = identity("Hello");
// 显式指定类型为 number
const result2 = identity<number>(42);
3. 高级复用技巧
(1)泛型约束与默认类型
// 约束 T 必须包含 length 属性
function logLength<T extends { length: number }>(arg: T): void {
console.log(arg.length);
}
// 默认类型参数
interface Pagination<T = string> {
items: T[];
page: number;
}
(2)结合条件类型
type Nullable<T> = T | null;
// 条件类型示例
type NonNullableProperty<T> = {
[P in keyof T]: T[P] extends null ? never : P;
}[keyof T];
4. 性能与可读性权衡
- 优点:减少重复代码,提高维护性
- 注意点:
- 避免过度复杂的嵌套泛型
- 适当使用类型别名简化复杂签名
- 在文档中明确泛型参数的用途
5. 实战建议
- 从具体到抽象:先实现具体类型的功能,再提取泛型
- 逐步迭代:先使用简单泛型,再逐步添加约束和条件
- 测试覆盖:为泛型代码编写针对不同类型参数的测试用例
最佳实践:在团队项目中建立泛型使用规范,例如:
- 单字母泛型参数(如
T,K,V)用于简单场景- 描述性泛型参数(如
TData,TResponse)用于复杂业务逻辑
总结
泛型是 TypeScript 强大类型系统的关键特性,合理使用可以显著提高代码的灵活性和可维护性。通过本章的学习,开发者应能够:
- 识别代码中可泛化的模式
- 设计类型安全的通用组件
- 平衡抽象程度与代码可读性
