TypeScript泛型的使用实践记录
TypeScript中的泛型(Generics)是一种在编写函数、类或接口时,可以将类型作为参数传递的机制,从而增加代码的灵活性和重用性。它允许我们在定义函数或类的时候不指定具体的类型,而是在实际使用时再传入具体的类型参数。以下是一些关于如何使用TypeScript中的泛型的实践记录:
1. 泛型函数
泛型函数:通过在函数声明中使用泛型,可以让函数适用于不同类型的参数,同时保持类型的安全性。常见的场景包括:
function identity<T>(value: T): T {
return value;
}
let result = identity("Hello, TypeScript");
// result 的类型为 string,因为传入的参数类型为 string
2. 泛型类
泛型类:在类的定义中使用泛型,可以创建能够处理不同类型数据的通用类。常见的场景包括:
class Box<T> {
private value: T;
constructor(value: T) {
this.value = value;
}
getValue(): T {
return this.value;
}
}
let boxOfString = new Box("TypeScript");
// boxOfString.getValue() 的类型为 string
let boxOfNumber = new Box(42);
// boxOfNumber.getValue() 的类型为 number
3. 泛型接口
泛型接口:可以使用泛型定义接口,使接口适用于不同的数据类型。
interface Pair<T, U> {
first: T;
second: U;
}
let pair: Pair<string, number> = { first: "one", second: 1 };
实例:
-
数组操作:在处理数组时,泛型可以帮助我们编写通用的函数,例如映射、筛选、查找等操作。
typescriptCopy code function mapArray<T, U>(array: T[], mapper: (item: T) => U): U[] { return array.map(mapper); } -
Promise和异步操作:泛型可以用于处理异步操作返回的结果,确保类型的正确性。
typescriptCopy code function asyncOperation<T>(data: T): Promise<T> { return new Promise(resolve => { // 异步操作 resolve(data); }); } -
默认类型参数
可以为泛型设置默认的类型参数,这在一些场景下非常有用。
function getValueOrDefault<T = number>(value: T, defaultValue: T): T {
return value !== undefined ? value : defaultValue;
}
let result = getValueOrDefault(undefined, 42);
// result 的类型为 number,默认使用了 number 类型的默认参数
4. 类型约束
可以使用类型约束来限制泛型的类型范围,使代码更安全。 以下是一些常见的类型约束使用场景:
function length<T extends { length: number }>(obj: T): number {
return obj.length;
}
let strLength = length("TypeScript");
let arrLength = length([1, 2, 3]);
let objLength = length({ length: 5 });
-
限制属性存在:通过约束确保传入的泛型类型拥有某些属性。
typescriptCopy code function getProperty<T, K extends keyof T>(obj: T, key: K) { return obj[key]; } -
限制类型范围:通过约束确保泛型类型属于特定的类型范围。
typescriptCopy code function ensurePositiveNumber<T extends number>(value: T): number { return value > 0 ? value : 0; } -
扩展已知类型:通过约束,可以使泛型继承已知类型的特性。
typescriptCopy code function mergeObjects<T, U>(obj1: T, obj2: U): T & U { return { ...obj1, ...obj2 }; } -
限制函数参数类型:约束函数参数的类型以保证类型安全。
typescriptCopy code function filterArray<T>(array: T[], predicate: (item: T) => boolean): T[] { return array.filter(predicate); }
通过泛型的类型约束,我们可以在编写通用代码时明确知道输入数据的类型,并在编译阶段捕获潜在的类型错误,从而增加代码的安全性和可维护性。无论是在函数、类、接口还是异步操作中,合理使用类型约束都能够让代码更加健壮和易于维护。
5. 使用泛型约束实现更具体的功能
泛型约束可以用于实现更具体的功能,例如在数组中查找某个元素。
function findElement<T>(arr: T[], predicate: (element: T) => boolean): T | undefined {
for (let element of arr) {
if (predicate(element)) {
return element;
}
}
}
let numbers = [1, 2, 3, 4, 5];
let result = findElement(numbers, n => n % 2 === 0);
// result 的类型为 number | undefined,找到第一个偶数
泛型在TypeScript中的应用非常广泛,可以用于各种情况下增加代码的灵活性和重用性。无论是函数、类、接口还是类型别名,都可以结合泛型来实现更具有通用性的代码。同时,通过使用类型约束,还可以增加代码的安全性和可靠性,避免一些潜在的错误。