Appearance
类的泛型支持
类与接口、函数一样,也支持泛型。通过泛型,我们可以创建可重用的组件,使其能够支持多种类型的数据,同时保持严格的类型检查。
基本用法
下面我们实现一个简易的 SimpleSet 类,它可以根据初始化时的数据自动推导存储的元素类型。
typescript
class SimpleSet<T> {
// 1. 实例属性使用泛型 T
private elements: Map<T, boolean>;
constructor(initialElements: T[] = []) {
this.elements = new Map<T, boolean>();
initialElements.forEach((element) => this.add(element));
}
// 2. 实例方法使用泛型 T,支持链式调用
add(element: T): this {
this.elements.set(element, true);
return this;
}
has(element: T): boolean {
return this.elements.has(element);
}
delete(element: T): boolean {
return this.elements.delete(element);
}
values(): T[] {
return Array.from(this.elements.keys());
}
// 3. 静态方法必须声明自己的泛型参数 E
static of<E>(...elements: E[]): SimpleSet<E> {
const set = new SimpleSet<E>();
elements.forEach((element) => set.add(element));
return set;
}
}
// 场景 A:显式指定泛型类型
const mySet = new SimpleSet<number>();
mySet.add(1).add(2);
// 场景 B:利用构造函数参数进行自动类型推导
const mySet2 = new SimpleSet(['a', 'b', 'c']); // 推导为 SimpleSet<string>
// 场景 C:调用静态工厂方法
const mySet3 = SimpleSet.of(100, 200, 300); // 推导为 SimpleSet<number>核心要点
1. 泛型的作用域
类声明上绑定的泛型 T 的作用域涵盖了所有的实例属性和实例方法。
2. 类型推导
如果在 new 实例化时没有显式指定类型(如 new SimpleSet<number>()),TypeScript 会尝试通过构造函数的参数来推导 T 的具体类型。如果构造函数没有参数且未指定类型,T 默认为 unknown。
3. 静态成员的限制
重要限制
类的静态成员不能访问类的泛型参数。
这是因为泛型参数 T 是在实例化时确定的,而静态成员属于类本身,不依赖于实例。因此,如果静态方法需要处理通用类型,必须像上面的 of<E> 方法一样,声明属于自己的泛型参数。
typescript
class Box<T> {
static value: T; // ❌ 错误:静态成员不能引用类的泛型参数
static show<U>(item: U) {
// ✅ 正确:静态方法声明自己的泛型 U
console.log(item);
}
}