TypeScript工厂模式优化:简化MainType实例获取调用方式
两种方案实现简化调用的单例工厂
我明白你想简化ItemFactory的调用逻辑,不用同时传递泛型参数和字符串标识,还得让TypeScript能自动推导返回类型。下面给你对应两种选项的可行实现方案:
选项2:只传字符串标识,自动推导返回类型
这种方案适合通过字符串key获取实例的场景,核心是建立字符串标识与对应类型的映射关系,让TypeScript自动完成类型关联:
class BaseType { } class MainType extends BaseType { } // 定义类型映射表:字符串标识 → 对应的类类型 type TypeMap = { "main-type": MainType; // 后续新增类型直接在这里扩展,比如 "other-type": OtherType; }; class ItemFactory { items: Partial<Record<keyof TypeMap, BaseType>> = {}; // 参数限制为TypeMap的key,返回值自动匹配对应类型 get<K extends keyof TypeMap>(type: K): TypeMap[K] { let item = this.items[type]; if (!item) { switch (type) { case "main-type": item = new MainType(); break; // 新增类型时同步添加case分支 default: // 用never类型检查确保所有TypeMap的key都被处理,避免遗漏 const _exhaustiveCheck: never = type; throw new Error(`Unknown type: ${type}`); } this.items[type] = item; } return item as TypeMap[K]; } } // 调用示例:仅传字符串,TypeScript自动推导返回MainType const resolvedType = itemFactory.get("main-type"); // 此时resolvedType的类型是MainType,完全不需要手动指定泛型
这里的关键是TypeMap,它把字符串标识和具体类型绑定死,get方法的参数被限制为keyof TypeMap,返回值直接取TypeMap[K],TypeScript就能自动完成类型推导。额外添加的never类型检查还能帮你避免遗漏新类型的case分支,算是个实用的小技巧。
选项1:只传泛型/类构造函数,自动匹配实例
这种方案适合强类型关联的场景,核心是建立类类型到字符串标识的反向映射,同时给子类添加静态标识:
class BaseType { // 给每个子类预留静态type标识位 static type?: string; } class MainType extends BaseType { static type = "main-type"; } // 定义反向类型映射:类构造函数 → 对应的字符串标识 type ConstructorToKey<T extends typeof BaseType> = T extends typeof MainType ? "main-type" : never; class ItemFactory { items: { [type: string]: BaseType } = {}; // 接收类构造函数作为参数,自动推导实例类型 get<T extends typeof BaseType>(typeConstructor: T): InstanceType<T> { const typeKey = typeConstructor.type as ConstructorToKey<T>; if (!typeKey) { throw new Error("Type constructor must have a static 'type' property"); } let item = this.items[typeKey]; if (!item) { switch (typeKey) { case "main-type": item = new MainType(); break; default: const _exhaustiveCheck: never = typeKey; throw new Error(`Unknown type: ${typeKey}`); } this.items[typeKey] = item; } return item as InstanceType<T>; } } // 调用示例:仅传类构造函数,自动推导返回实例类型 const resolvedType = itemFactory.get(MainType); // 此时resolvedType的类型是MainType,无需传递字符串
如果你执着于完全不用传构造函数、只写get<MainType>()的写法,需要维护更复杂的实例类型到key的映射,但TypeScript没法自动完成这种反向推断,实际使用起来反而不如传构造函数直观。上面的写法已经是最简洁的"仅传类型相关参数"的实现方式了。
两种方案可以根据你的实际使用场景选择:选项2适合通过配置字符串获取实例的场景,选项1更适合强调强类型绑定的场景。
内容的提问来源于stack exchange,提问作者zhuber
相关产品推荐
相关产品推荐

