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

如何创建符合泛型接口的枚举类映射?TypeScript技术问询

TypeScript泛型工厂模式的类型约束问题

我见过的大多数TypeScript工厂模式都是基于名称与类构造函数的映射实现,简易代码如下:

const myMap = {
 classOne: ExampleClass,
 classTwo: AnotherClass
}

(k: string) => { return new myMap[k] }

我希望升级这种实现——我的类都遵循ExampleClass implements iGenericInterface<T>的形式,但无法正确定义映射的类型约束,让编译器只接受实现了iGenericInterface<T>的类。以下示例中标记***的位置是核心问题点:

export interface iGenericInterface<K> {
  process(input: K): void
}

class ExampleClass implements iGenericInterface<string> {
  process(input: string): void {
    console.log(input);
  }
}

class AnotherClass implements iGenericInterface<number> {
  process(input: number): void {
    console.log(input);
  }
}

class UnsupportedClass {
  otherMethod(input: boolean): void {
    console.log(input);
  }
}

enum instantiableClassesEnum { class1, class2, class3 };
type enumValues = keyof typeof instantiableClassesEnum;
type logicStore<T> = Record<enumValues, ***iGenericInterface<T>***>

const classMap: logicStore<any> = {
    class1: ExampleClass,
    class2: AnotherClass,
    class3: UnsupportedClass,
};

我需要编译器对UnsupportedClass报错,同时正常接受其他类。如果把ExampleClass改成实例(比如class1: new ExampleClass()),编译器不会报错,但这样就没法在工厂方法return new myMap[k]中使用这个映射了。

我的最终目标是基于枚举输入创建类,实现如下工厂:

class LogicFactory {
  static createLogic<T>(logicClass: enumValues): iGenericInterface<T> {
    return new classMap[logicClass]();
  }
}

解决方案

1. 定义构造函数类型

首先要明确:映射中存储的是类的构造函数,而不是类的实例。先定义一个构造函数类型,用来描述能生成iGenericInterface实例的类:

// 无参构造,返回实现iGenericInterface的实例
type Constructable<T> = new () => T;

2. 修正映射的类型约束

把logicStore的类型改为存储符合要求的构造函数,这样就能过滤掉未实现接口的类:

// 约束映射值为能生成iGenericInterface实例的构造函数
type logicStore = Record<enumValues, Constructable<iGenericInterface<unknown>>>;

const classMap: logicStore = {
    class1: ExampleClass,
    class2: AnotherClass,
    // 此处编译器会报错:UnsupportedClass的实例未实现iGenericInterface
    class3: UnsupportedClass,
};

3. 优化工厂方法的类型推断

如果希望工厂方法能根据传入的枚举值自动推断返回的泛型类型(而非手动指定T),可以建立枚举与泛型参数的映射关系:

// 建立枚举值与对应泛型参数的映射
type LogicTypeMap = {
  [instantiableClassesEnum.class1]: string;
  [instantiableClassesEnum.class2]: number;
};

class LogicFactory {
  static createLogic<K extends instantiableClassesEnum>(
    logicClass: K
  ): iGenericInterface<LogicTypeMap[K]> {
    // 类型断言确保类型匹配
    return new classMap[logicClass]() as iGenericInterface<LogicTypeMap[K]>;
  }
}

调用时编译器会自动推断返回类型:

// 自动推断返回iGenericInterface<string>
const logic1 = LogicFactory.createLogic(instantiableClassesEnum.class1);
logic1.process("test"); // 正常

// 自动推断返回iGenericInterface<number>
const logic2 = LogicFactory.createLogic(instantiableClassesEnum.class2);
logic2.process(123); // 正常

内容的提问来源于stack exchange,提问作者redevill

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 14:25:23