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

如何用枚举实现TypeScript多态工厂方法?

TypeScript 枚举关联参数类型的工厂方法实现

我有一个如下签名的工厂方法:

enum FactoryType {
  CAR = 'CAR',
  BIKE = 'BIKE'
}

type CarParamType = {
  cylinders: number
}

type BikeParamType = {
  gears: number
}

factory<F extends FactoryType>(factoryType: F, params: ParamType<F>) {
  switch (factoryType) {
    case FactoryType.CAR:
      return new CarFactory(params);
    case FactoryType.BIKE:
      return new BikeFactory(params);
    default:
       throw new Error('unrecognized factory');
  }
}

其中BikeFactory和CarFactory的构造函数会接收各自对应的参数类型。请问能否在TypeScript中实现这一需求?即通过枚举确定ParamType的实际类型,避免在工厂方法中将params传入对应构造函数时出现编译错误?

我原本设想ParamType的定义如下:

type ParamType<T> = T extends FactoryType.CAR ? CarParamType
  : T extends FactoryType.BIKE ? BikeParamType : never;

但我认为这样的定义无法为编译器提供足够的类型提示。


可以实现,优化方案如下

你的ParamType定义方向是对的,只需调整类型关联方式和工厂函数写法,就能让TypeScript正确识别枚举与参数类型的对应关系,解决编译错误的同时提供精准类型提示:

1. 用映射类型优化ParamType定义

先定义枚举到参数类型的映射表,比条件类型更直观,后续扩展枚举值时只需更新映射表:

// 枚举与参数类型的映射关系
type FactoryParamMap = {
  [FactoryType.CAR]: CarParamType;
  [FactoryType.BIKE]: BikeParamType;
};

// 基于映射表定义ParamType
type ParamType<T extends FactoryType> = FactoryParamMap[T];

2. 解决工厂函数的分支类型推导问题

TypeScript无法自动将泛型F extends FactoryType在switch分支中缩小到具体枚举值,可通过两种方式解决:

方案一:类型断言快速修复编译错误

如果追求实现简洁,直接在分支中给params添加类型断言即可:

class CarFactory {
  constructor(params: CarParamType) {}
}

class BikeFactory {
  constructor(params: BikeParamType) {}
}

function factory<F extends FactoryType>(factoryType: F, params: ParamType<F>) {
  switch (factoryType) {
    case FactoryType.CAR:
      return new CarFactory(params as CarParamType);
    case FactoryType.BIKE:
      return new BikeFactory(params as BikeParamType);
    default:
      throw new Error('unrecognized factory');
  }
}

方案二:函数重载实现精准类型提示

如果想要调用时自动关联参数类型、分支内无需断言,推荐使用函数重载:

// 重载签名:定义每种枚举对应的参数和返回类型
function factory(factoryType: FactoryType.CAR, params: CarParamType): CarFactory;
function factory(factoryType: FactoryType.BIKE, params: BikeParamType): BikeFactory;

// 实现签名:统一处理逻辑
function factory(factoryType: FactoryType, params: FactoryParamMap[FactoryType]) {
  switch (factoryType) {
    case FactoryType.CAR:
      return new CarFactory(params);
    case FactoryType.BIKE:
      return new BikeFactory(params);
    default:
      throw new Error('unrecognized factory');
  }
}

效果验证

调用工厂函数时,TypeScript会自动根据枚举值校验参数类型:

// 正确:参数匹配CAR类型
const car = factory(FactoryType.CAR, { cylinders: 6 });
// 错误:缺少cylinders参数,编译报错
const badCar = factory(FactoryType.CAR, {});
// 正确:参数匹配BIKE类型
const bike = factory(FactoryType.BIKE, { gears: 10 });

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 05:39:52