TypeScript 泛型
泛型(Generics)是 TypeScript 中最强大的特性之一。它允许我们编写可重用的、灵活的组件(如函数、类或接口),这些组件可以处理多种数据类型,而不仅仅是单一的一种。这在保持类型安全的同时,极大地提高了代码的复用性。
为什么需要泛型?
想象一个简单的函数,它接收一个参数并直接返回它。
typescript
// 使用 any 类型,但会丢失类型信息
function identity_any(arg: any): any {
return arg;
}
// 使用特定类型,但无法复用
function identity_number(arg: number): number {
return arg;
}使用 any 类型会导致函数失去类型安全,因为编译器不知道返回值的具体类型。而为每种类型都写一个函数又非常繁琐。泛型就是为了解决这个问题而生的。
创建泛型函数
我们可以创建一个泛型函数 identity,它适用于所有类型。
typescript
function identity<T>(arg: T): T {
return arg;
}这里,<T> 是一个类型变量,它是一种特殊的变量,只用于表示类型而不是值。它捕获了用户传入的类型(比如 number),然后我们就可以在函数内部使用这个类型。
使用泛型函数
有两种方式来使用泛型函数:
显式传入类型参数:
typescriptlet output = identity<string>("myString"); // output 的类型是 string类型推断: 编译器会根据传入的参数自动确定
T的类型。typescriptlet output = identity("myString"); // 编译器推断 T 为 string,output 的类型是 string let numOutput = identity(123); // 编译器推断 T 为 number,numOutput 的类型是 number
泛型约束 (Generic Constraints)
有时候,我们希望泛型函数能处理一些具有特定属性的类型。例如,一个日志函数可能需要访问参数的 .length 属性。在这种情况下,我们可以使用泛型约束。
我们可以创建一个接口来描述约束条件,然后使用 extends 关键字来应用它。
typescript
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // 现在我们可以安全地访问 .length 属性
return arg;
}
loggingIdentity("hello"); // OK, string 有 length 属性
loggingIdentity([1, 2, 3]); // OK, array 有 length 属性
// loggingIdentity(123); // Error: number 没有 length 属性
// loggingIdentity({ name: 'test' }); // Error: { name: string } 没有 length 属性泛型接口
我们也可以创建泛型接口,让接口的成员类型可以灵活变化。
typescript
interface GenericIdentityFn<T> {
(arg: T): T;
}
function identity<T>(arg: T): T {
return arg;
}
let myIdentity: GenericIdentityFn<number> = identity;
console.log(myIdentity(100)); // 100
// console.log(myIdentity("test")); // Error泛型类
类也可以是泛型的。泛型类在类名后使用 <T> 来定义类型参数。
typescript
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
// string 类型的泛型类实例
let myGenericString = new GenericNumber<string>();
myGenericString.zeroValue = "";
myGenericString.add = function(x, y) { return x + y; };
console.log(myGenericString.add("hello", " world")); // "hello world"
// number 类型的泛型类实例
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
console.log(myGenericNumber.add(10, 20)); // 30泛型是 TypeScript 类型系统中一个非常重要的部分,掌握它可以让你编写出更通用、更健壮、更具可重用性的代码。