在 TypeScript 中,泛型(Generics)是一种在函数、类或接口中使用参数化类型的机制。它允许我们编写可以适用于不同类型的代码,增加代码的灵活性和可重用性。
1、泛型的作用
- 类型安全性:使用泛型可以在编译时捕获类型错误,避免在运行时出现类型不匹配的错误。通过指定泛型类型参数,可以确保函数或类在处理数据时使用正确的类型,提高代码的可靠性和安全性。
- 代码重用性:泛型可以使得代码更通用,可以在多个地方使用相同的逻辑,但适用于不同的数据类型。这样可以避免重复编写类似的代码,提高代码的重用性和可维护性。
下面通过几个例子来详细说明 TypeScript 中泛型的使用
(1)、泛型函数
function reverse<T>(arr: T[]): T[] { return arr.reverse(); } const numbers = [1, 2, 3, 4, 5]; const strings = ['apple', 'banana', 'cherry']; console.log(reverse(numbers)); // [5, 4, 3, 2, 1] console.log(reverse(strings)); // ['cherry', 'banana', 'apple']
在上述例子中,我们定义了一个泛型函数 reverse
,它接受一个数组 arr
,并返回一个反转后的数组。通过使用泛型类型参数 T
,我们可以确保输入数组和输出数组的类型一致。在调用 reverse
函数时,编译器会根据传入的实际类型推断并应用泛型参数的类型。
(2)、泛型类
class Stack<T> { private items: T[] = []; push(item: T): void { this.items.push(item); } pop(): T | undefined { return this.items.pop(); } } const numberStack = new Stack<number>(); numberStack.push(1); numberStack.push(2); numberStack.push(3); console.log(numberStack.pop()); // 3 const stringStack = new Stack<string>(); stringStack.push('apple'); stringStack.push('banana'); stringStack.push('cherry'); console.log(stringStack.pop()); // 'cherry'
在上述例子中,我们定义了一个泛型类 Stack
,它表示一个栈数据结构。通过使用泛型类型参数 T
,我们可以在实例化类时指定栈中元素的类型。这样可以确保栈中的元素类型与指定的类型一致。
(3)、泛型接口
interface Pair<T, U> { first: T; second: U; } const pair: Pair<number, string> = { first: 1, second: 'two', }; console.log(pair.first); // 1 console.log(pair.second); // 'two'
在上述例子中,我们定义了一个泛型接口 Pair
,它表示一对具有不同类型的值。通过使用泛型类型参数 T
和 U
,我们可以在创建 Pair
对象时指定不同的类型。这样可以确保 Pair
对象中的属性类型与指定的类型一致。
通过泛型,可以编写更通用、灵活和类型安全的代码。它使我们能够在不同的情况下使用相同的逻辑,但适用于不同的类型。这提高了代码的重用性和可维护性,并减少了类型错误的风险。