TypeScript中的泛型
导读
近端时间面试一直提到``TypeScript`存在泛型,那么什么是泛型,有什么作用,实际的使用场景是什么呢?
泛型的定义
一个概念,不管如何,首先从定义入手。
泛型(Generics)通过类型参数(Type Parameters)实现,类型参数是一个占位符,表示未来使用时可以传入的具体类型。在TypeScript中,泛型通常使用尖括号
泛型的基本语法
函数中的泛型
1
2
3function identity<T>(arg: T): T {
return arg;
}T
是类型参数,表示传入和返回的类型。- 调用时可以显式指定类型,也可以让 TypeScript 自动推断。
类中的泛型
typescript
复制
1
2
3
4
5
6
7
8
9class Box<T> {
private value: T;
constructor(value: T) {
this.value = value;
}
getValue(): T {
return this.value;
}
}T
是类的类型参数,用于定义类的属性和方法。
接口中的泛型
1
2
3
4interface Pair<T, U> {
first: T;
second: U;
}T
和U
是接口的类型参数,用于定义接口的成员类型。
泛型的核心特点
- 类型占位符
- 泛型通过类型参数(如
<T>
)表示一个占位符,具体类型在使用时确定。 - 例如,
identity<T>
中的T
可以是string
、number
或任何其他类型。
- 泛型通过类型参数(如
- 类型安全
- 泛型在编译时保留类型信息,避免运行时类型错误。
- 例如,
Box<number>
确保value
只能是number
类型。
- 代码复用
- 泛型允许编写通用的逻辑,适用于多种类型,减少重复代码。
- 例如,
identity<T>
可以处理任何类型,而不需要为每种类型单独编写函数。
泛型的应用场景
通用函数
例如,一个可以处理任意类型数组的函数:
typescript
复制
1
2
3
4
5function logArray<T>(arr: T[]): void {
arr.forEach(item => console.log(item));
}
logArray<number>([1, 2, 3]); // 处理数字数组
logArray<string>(["a", "b", "c"]); // 处理字符串数组
通用数据结构
例如,一个通用的栈类:
typescript
复制
1
2
3
4
5
6
7
8
9
10
11
12class 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);
类型约束
通过泛型约束(
extends
)限制类型参数的范围:typescript
复制
1
2
3
4
5
6function getLength<T extends { length: number }>(arg: T): number {
return arg.length;
}
getLength("hello"); // 5
getLength([1, 2, 3]); // 3
// getLength(42); // 错误:数字没有 length 属性
工具类型
TypeScript 内置的泛型工具类型(如
Partial
、Readonly
等):typescript
复制
1
2
3
4
5interface User {
name: string;
age: number;
}
type PartialUser = Partial<User>; // { name?: string; age?: number; }
总结
泛型的定义可以概括为:
- 泛型是一种编程机制,允许在定义函数、类、接口或类型时使用类型参数作为占位符,从而在使用时动态指定具体类型。
- 泛型的核心目标是提高代码的复用性和类型安全性,适用于需要处理多种类型的场景。
通过泛型,开发者可以编写更通用、更灵活的代码,同时保持类型系统的强大支持。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 程序员零塔的小破站!
评论