返回
精解泛型在 TypeScript 中的本质和用法
前端
2023-11-16 22:32:39
泛型概述
泛型允许你使用占位符来表示类型,这样你就可以在代码中使用这些占位符来表示任何类型的数据。例如,以下代码中的 T
就是一个占位符:
function identity<T>(x: T): T {
return x;
}
这个 identity
函数接受任何类型的数据作为参数,并将该参数原样返回。因为我们使用了泛型,所以我们可以使用 identity
函数来处理任何类型的数据,而不需要为每种数据类型创建单独的函数。
泛型函数
泛型函数是接受泛型参数的函数。泛型参数允许你定义函数的通用行为,而不需要为每种数据类型创建单独的函数。例如,以下代码中的 map
函数是一个泛型函数:
function map<T, U>(array: T[], f: (x: T) => U): U[] {
return array.map(f);
}
这个 map
函数接受一个数组和一个函数作为参数,并将该数组的每个元素映射到另一个值。因为我们使用了泛型,所以我们可以使用 map
函数来处理任何类型的数据,而不需要为每种数据类型创建单独的函数。
泛型接口
泛型接口是定义泛型类型的接口。泛型接口允许你创建可重用的类型,而无需为每种数据类型创建单独的类型。例如,以下代码中的 List
接口是一个泛型接口:
interface List<T> {
add(x: T): void;
remove(x: T): void;
get(index: number): T;
size(): number;
}
这个 List
接口定义了一个列表类型,该列表可以存储任何类型的数据。因为我们使用了泛型,所以我们可以使用 List
接口来创建任何类型的数据的列表,而不需要为每种数据类型创建单独的接口。
泛型类
泛型类是定义泛型类型的类。泛型类允许你创建可重用的类,而无需为每种数据类型创建单独的类。例如,以下代码中的 Stack
类是一个泛型类:
class Stack<T> {
private _items: T[] = [];
push(x: T): void {
this._items.push(x);
}
pop(): T | undefined {
return this._items.pop();
}
peek(): T | undefined {
return this._items[this._items.length - 1];
}
size(): number {
return this._items.length;
}
}
这个 Stack
类定义了一个栈类型,该栈可以存储任何类型的数据。因为我们使用了泛型,所以我们可以使用 Stack
类来创建任何类型的数据的栈,而不需要为每种数据类型创建单独的类。
泛型的优势
泛型具有以下优势:
- 代码重用:泛型可以让你创建可重用的组件,而无需为每种数据类型创建单独的组件。这可以节省大量的代码量,并使你的代码更容易维护。
- 代码简洁:泛型可以使你的代码更加简洁。例如,以下代码使用泛型来定义一个
map
函数:
function map<T, U>(array: T[], f: (x: T) => U): U[] {
return array.map(f);
}
这段代码比以下代码更加简洁:
function mapNumberArray(array: number[], f: (x: number) => number): number[] {
return array.map(f);
}
function mapStringArray(array: string[], f: (x: string) => string): string[] {
return array.map(f);
}
- 代码灵活性:泛型可以使你的代码更加灵活。例如,你可以使用泛型来创建