You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:09:10