TypeScript中如何实例化泛型抽象工厂的泛型类型?
解决TypeScript泛型抽象工厂的重复代码问题
首先明确:你最初的代码无法运行,核心原因是TypeScript编译后会擦除泛型类型信息,运行时new T(attribute)里的T没有对应的构造函数实体,必然抛出错误。
下面提供两种重构方案,彻底消除重复的工厂类代码:
方案一:改造泛型工厂类,注入构造函数
让抽象工厂类接收Item的构造函数作为实例依赖,在create方法中复用该构造函数创建实例:
// 定义Item构造函数的类型约束,保证类型安全 type ItemConstructor<T extends Item> = new (attribute: ConstructorParameters<typeof T>[0]) => T; abstract class GenericItemFactory<T extends Item> { protected constructor(private readonly itemCtor: ItemConstructor<T>) {} create(attribute: ConstructorParameters<typeof this.itemCtor>[0]): T { return new this.itemCtor(attribute); } } // 具体工厂只需传入构造函数,无需重写create class ItemAFactory extends GenericItemFactory<ItemA> { constructor() { super(ItemA); } } class ItemBFactory extends GenericItemFactory<ItemB> { constructor() { super(ItemB); } }
每个具体工厂类仅需一行构造函数代码,完全消除了重复的create方法逻辑。
方案二:用高阶函数直接生成工厂实例(更简洁)
如果连工厂子类都不想定义,可以用一个工具函数直接生成带有create方法的工厂对象,彻底省去所有工厂类:
type ItemConstructor<T extends Item> = new (attribute: ConstructorParameters<typeof T>[0]) => T; function createItemFactory<T extends Item>(itemCtor: ItemConstructor<T>) { return { create: (attribute: ConstructorParameters<typeof itemCtor>[0]): T => { return new itemCtor(attribute); } }; } // 直接生成各Item的工厂实例,新增Item仅需添加一行 const items = { itemA: createItemFactory(ItemA), itemB: createItemFactory(ItemB), itemC: createItemFactory(ItemC), // ...后续新增项 };
这种方式无需定义GenericItemFactory类,所有重复逻辑都封装在createItemFactory函数中,是代码量最少的实现方式。
补充:优化类型安全(替换any)
上述代码使用ConstructorParameters工具类型自动推导构造函数的参数类型,避免了any的滥用,让整个工厂体系的类型检查更严格。比如ItemA的构造函数若需要特定类型的attribute,TypeScript会自动在create方法中提示对应的参数类型。
内容的提问来源于stack exchange,提问作者Joshua Ohana
相关产品推荐
相关产品推荐

