泛型类
TypeScript 的泛型类允许开发者创建可复用的组件,这些组件能够处理多种数据类型而不牺牲类型安全。泛型类通过类型参数在类定义时引入灵活性,使得同一个类可以适应不同的类型需求。
泛型类的基本语法
泛型类在类名后使用尖括号 <T>
声明类型参数,T
是类型变量的占位符,实际使用时会被具体类型替换。例如:
class Box<T> {
private content: T;
constructor(value: T) {
this.content = value;
}
getValue(): T {
return this.content;
}
}
const numberBox = new Box<number>(42);
const stringBox = new Box<string>("Hello");
这里 Box
类通过 <T>
声明泛型参数,content
属性和 getValue
方法的类型都依赖于 T
。实例化时分别指定 number
和 string
类型,使得类型检查能够针对不同场景生效。
泛型约束与默认类型
泛型类可以通过 extends
添加约束,限制类型参数的范围。同时支持为泛型参数提供默认类型:
interface HasLength {
length: number;
}
class Container<T extends HasLength = string> {
constructor(private data: T) {}
logLength(): void {
console.log(this.data.length);
}
}
const strContainer = new Container("abc"); // 使用默认类型 string
const arrContainer = new Container<number[]>([1, 2, 3]); // 显式指定类型
此例中 T
必须满足 HasLength
接口,且默认类型为 string
。尝试使用不包含 length
属性的类型会导致编译错误。
多类型参数应用
泛型类支持多个类型参数,适用于需要处理多种关联类型的场景:
class Pair<K, V> {
constructor(
public key: K,
public value: V
) {}
swap(): Pair<V, K> {
return new Pair(this.value, this.key);
}
}
const nameAge = new Pair<string, number>("Alice", 30);
const swapped = nameAge.swap(); // 类型变为 Pair<number, string>
Pair
类通过 <K, V>
定义两个泛型参数,在 swap
方法中实现类型位置的互换,保持类型系统的完整性。
静态成员的限制
需注意泛型类的静态成员不能引用类的类型参数:
class GenericStatic<T> {
static defaultValue: T; // 错误:静态成员不能引用类型参数
instanceValue: T; // 正确
}
这是因为静态成员属于类本身而非实例,而泛型参数在实例化时才会确定具体类型。
与泛型接口结合使用
泛型类可以实现泛型接口,形成更灵活的类型体系:
interface IRepository<T> {
getById(id: string): T;
save(entity: T): void;
}
class UserRepository implements IRepository<User> {
getById(id: string): User {
// 实现逻辑
}
save(user: User): void {
// 实现逻辑
}
}
复杂类型推断示例
泛型类在复杂类型场景中能自动推断类型关系:
class TreeNode<T> {
constructor(
public value: T,
public left: TreeNode<T> | null = null,
public right: TreeNode<T> | null = null
) {}
}
const tree = new TreeNode(1, new TreeNode(2), new TreeNode(3));
// 自动推断为 TreeNode<number>
类型擦除的运行时行为
虽然 TypeScript 在编译时会进行类型检查,但运行时泛型类型信息会被擦除:
class Erasure<T> {
constructor(private data: T) {}
}
const instance1 = new Erasure<string>("test");
const instance2 = new Erasure<number>(123);
console.log(instance1 instanceof Erasure); // true
console.log(instance2 instanceof Erasure); // true
// 运行时无法区分 Erasure<string> 和 Erasure<number>
高级模式:递归泛型
泛型类可以定义递归类型结构,适用于自引用数据模型:
class NestedArray<T> {
constructor(public items: Array<T | NestedArray<T>>) {}
flatten(): T[] {
return this.items.reduce((acc: T[], item) => {
return acc.concat(item instanceof NestedArray ? item.flatten() : item);
}, []);
}
}
const nested = new NestedArray([1, [new NestedArray([2, 3]), 4]);
console.log(nested.flatten()); // [1, 2, 3, 4]
工厂函数与泛型类结合
通过工厂函数创建泛型类实例时,可以保留完整的类型信息:
function createComponent<T>(ctor: new () => T): T {
return new ctor();
}
class Button {
click() {
console.log("Clicked!");
}
}
const button = createComponent(Button); // 类型推断为 Button
button.click();
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn