TypeScript中如何实例化泛型类?两种场景实现方案
TypeScript中泛型类实例的创建方法(两种场景)
TypeScript里创建泛型类实例的核心问题是类型擦除——编译后泛型类型信息会被移除,没法直接通过new T()创建实例,必须把类型的构造函数显式传入。下面分两种场景解决你的问题:
场景1:编译时已知类型参数
先修正你的Buz泛型类写法,泛型约束要用extends而非implements,同时要接收对应类型的构造函数作为参数(因为没法直接用T来实例化):
interface ITheValue { TheValue: string; } class Foo implements ITheValue { TheValue: string; constructor(val: string) { this.TheValue = val; } } class Bar implements ITheValue { TheValue: string; constructor(val: string) { this.TheValue = val; } } // 修正泛型类:约束T为ITheValue的实现类,同时接收T的构造函数 class Buz<T extends ITheValue> { Thing: T; // 构造函数接收两个参数:T的构造器、初始化值 constructor(private ctor: new (val: string) => T, val: string) { this.Thing = new ctor(val); } getTheValue(): string { return this.Thing.TheValue; } }
现在编译时已知类型(比如Foo),直接传入构造器就能创建实例:
function runKnownType(theValue: string): string { // 直接传入Foo的构造函数作为第一个参数 const buz = new Buz(Foo, theValue); return `The value is: ${buz.getTheValue()}.`; } // 调用示例 console.log(runKnownType("foo test value")); // 输出:The value is: foo test value.
场景2:通过字符串值指定类型名称
这种情况需要先建立字符串到类构造器的映射表,根据传入的字符串找到对应的构造函数,再创建泛型实例:
// 建立字符串到构造器的映射 const typeMap: Record<string, new (val: string) => ITheValue> = { Foo: Foo, Bar: Bar }; function runByTypeName(whichOne: string, theValue: string): string { // 根据字符串获取对应的构造器,先做合法性检查 const ctor = typeMap[whichOne]; if (!ctor) { throw new Error(`Unknown type: ${whichOne}`); } // 传入构造器创建泛型实例 const buz = new Buz(ctor, theValue); return `The value is: ${buz.getTheValue()}.`; } // 调用示例 console.log(runByTypeName("Bar", "bar test value")); // 输出:The value is: bar test value.
关键说明
- 为什么不能直接
new T()?因为TypeScript的泛型是编译时语法糖,编译成JS后T会被替换成any或对应的约束类型,没有实际的构造函数信息,必须显式传入构造器。 - 泛型约束要用
extends:对于类/接口的约束,TypeScript里泛型语法是T extends 类型,而不是implements。 - 字符串映射的安全性:如果要更严谨,可以把
whichOne的类型定义为keyof typeof typeMap,这样TypeScript会在编译时检查传入的字符串是否合法:
function runByTypeName(whichOne: keyof typeof typeMap, theValue: string): string { // ... 内部逻辑不变 }
内容的提问来源于stack exchange,提问作者Richard Barraclough
相关产品推荐
相关产品推荐

