TypeScript泛型工厂模式基类控制器报类型当值使用错误
问题原因
TypeScript泛型参数仅在编译阶段做类型校验,编译为JavaScript后会被完全擦除,运行时不存在对应的值,因此直接写new X()会触发报错:
'X' only refers to a type, but is being used as a value here
之前用抽象模型基类的思路没解决问题,核心是没有把模型的构造函数(运行时可访问的值)传入基类逻辑,泛型本身无法携带运行时的构造器引用。另外注意纯接口类型同样会在编译后擦除,没有运行时构造逻辑,无法直接实例化,需要配套实现类才能创建实例。
可行实现方案
核心思路是显式传入模型对应的构造函数引用,让运行时可以拿到构造器完成实例初始化,同时保留完整的类型校验能力。
// 定义无参模型构造函数的类型约束 type ModelCtor<T> = new () => T; // 模型抽象基类,所有可实例化业务模型继承该类 abstract class BaseModel {} // 业务模型A class ModelA extends BaseModel { propA: string; propB?: number; propC?: number; constructor() { super(); this.propA = "here"; } } // 原接口ModelB无运行时实现,补充对应实现类用于实例化 class ModelBImpl extends BaseModel { propA: string; propB: number; propC: number; constructor() { super(); this.propA = "defaultB"; this.propB = 0; this.propC = 0; } } interface ModelB { propA: string; propB: number; propC: number; } // 泛型基类控制器 class BaseController<T extends BaseModel> { private _model: T; constructor(payload: T) { this._model = payload; } // 基类静态工厂方法,接收模型构造器完成初始化 static create<T extends BaseModel>( this: new (payload: T) => BaseController<T>, modelCtor: ModelCtor<T> ): BaseController<T> { const model = new modelCtor(); return new this(model); } // 通用模型访问方法,可按需扩展其他通用业务逻辑 get model(): T { return this._model; } } // 业务控制器A,绑定ModelA构造器 class ModelAController extends BaseController<ModelA> { static create(): ModelAController { return super.create(ModelA) as ModelAController; } } // 业务控制器B,绑定ModelBImpl构造器 class ModelBController extends BaseController<ModelBImpl> { static create(): ModelBController { return super.create(ModelBImpl) as ModelBController; } } // 调用示例:直接通过工厂方法创建控制器,内部已自动初始化带默认值的模型 const aController = ModelAController.create(); console.log(aController.model.propA); // 输出 "here" const bController = ModelBController.create(); console.log(bController.model.propB); // 输出 0
方案说明
- 所有类型校验逻辑完整保留,调用方拿到的控制器、内部模型的类型提示完全准确
- 业务控制器仅需在静态
create方法中绑定一次对应模型的构造器,无重复样板代码 - 若需要支持带参数的模型构造,只需修改
ModelCtor的类型定义、调整工厂方法传参即可快速适配 - 禁止直接使用纯接口作为可实例化的模型泛型参数,接口无运行时实现,必须提供对应构造逻辑(实现类/工厂函数)
内容的提问来源于stack exchange,提问作者300baud
相关产品推荐
相关产品推荐

