TypeScript 泛型是一种强大的工具,它允许你创建可复用的组件,适用于多种数据类型,而无需在每次使用时指定具体类型。泛型使代码更加灵活和可扩展。以下是对 TypeScript 泛型的详细介绍,包括泛型变量、泛型类型、泛型类、泛型约束及学习技巧。
1. 泛型概述
泛型(Generics)允许定义函数、类或接口时不指定具体类型,而是在使用时再指定具体类型。这种方式使得代码在保持类型安全的同时,具有更高的灵活性。
2. 泛型变量
泛型变量用来捕获传递给函数、类或接口的类型。
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("Hello");
let output2 = identity<number>(123);
identity<T>(arg: T): T
中的T
就是泛型变量。- 调用时指定具体类型,例如
identity<string>("Hello")
。
3. 泛型类型
泛型类型用于定义包含一个或多个类型参数的类型。
type GenericIdentityFn<T> = (arg: T) => T;
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
type GenericIdentityFn<T> = (arg: T) => T
定义了一个泛型类型别名。let myIdentity: GenericIdentityFn<number> = identity
使用泛型类型别名定义变量。
4. 泛型类
泛型类允许类在实例化时指定类型。
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
constructor(zeroValue: T, add: (x: T, y: T) => T) {
this.zeroValue = zeroValue;
this.add = add;
}
}
let myGenericNumber = new GenericNumber<number>(0, (x, y) => x + y);
console.log(myGenericNumber.add(myGenericNumber.zeroValue, 5)); // 输出 5
class GenericNumber<T>
定义了一个泛型类。new GenericNumber<number>(0, (x, y) => x + y)
实例化时指定具体类型。
5. 泛型约束
泛型约束用于限制泛型类型的范围。
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // 现在可以访问length属性
return arg;
}
loggingIdentity({ length: 10, value: 3 });
T extends Lengthwise
表示泛型类型T
必须满足Lengthwise
接口的约束。- 这样可以确保
T
类型具有length
属性。
6. 学习技巧
要掌握 TypeScript 泛型,可以采用以下学习技巧:
- 从简单示例入手:理解基本概念后,再逐步复杂化。
- 阅读官方文档:TypeScript 官方文档是最权威的学习资源,涵盖了泛型的方方面面。
- 实践练习:多写代码,尝试将常见的非泛型代码改写成泛型代码。
- 阅读开源项目代码:学习他人如何在大型项目中使用泛型。
- 使用TypeScript Playground:在TypeScript Playground 上实验代码,快速验证想法。
综合示例
以下是一个综合示例,展示了如何使用泛型函数、泛型接口和泛型类:
// 泛型函数
function merge<T, U>(obj1: T, obj2: U): T & U {
return { ...obj1, ...obj2 };
}
const mergedObj = merge({ name: "Alice" }, { age: 25 });
console.log(mergedObj.name, mergedObj.age);
// 泛型接口
interface Result<T> {
success: boolean;
data: T;
}
function fetchData<T>(url: string): Result<T> {
// 模拟请求
const data: T = JSON.parse(`{"data": "example"}`);
return { success: true, data };
}
const result = fetchData<{ message: string }>("http://example.com");
console.log(result.data.message);
// 泛型类
class DataStorage<T> {
private items: T[] = [];
addItem(item: T) {
this.items.push(item);
}
removeItem(item: T) {
this.items = this.items.filter(i => i !== item);
}
getItems(): T[] {
return [...this.items];
}
}
const textStorage = new DataStorage<string>();
textStorage.addItem("Alice");
textStorage.addItem("Bob");
textStorage.removeItem("Alice");
console.log(textStorage.getItems());
通过这些示例,可以全面理解 TypeScript 中泛型的使用和优势。多加练习,可以更好地掌握和应用泛型,使代码更加通用和可复用。