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

TypeScript根据类型动态生成类实例 消除多if-else的实现方案

实现方案

完全可以通过**工厂注册表(映射表)**模式替代多分支if/else判断,这也是工厂策略模式在TypeScript中的标准落地方式,实现后新增产品类型无需修改工厂函数核心逻辑,符合开闭原则。

首先先修正原有代码的类型定义问题:原代码中type字段使用宽泛的string类型,无法做合法值校验,先和数据库枚举对齐定义严格的类型约束:

// 和数据库存储的枚举值一一对应
type ProductType = 'prod1' | 'prod2' | 'prod3';

interface Product {
  readonly type: ProductType;
  name(): string;
}

class Product1 implements Product {
  readonly type = 'prod1' as const;
  name() {
    return 'Product 1';
  }
}

class Product2 implements Product {
  readonly type = 'prod2' as const;
  name() {
    return 'Product 2';
  }
}

class Product3 implements Product {
  readonly type = 'prod3' as const;
  name() {
    return 'Product 3';
  }
}

基础实现:手动维护映射表

核心思路是提前建立「产品类型值 -> 对应类构造函数」的键值映射,工厂函数直接通过key取到构造函数实例化即可,不需要任何分支判断:

// 类型到类构造函数的注册表
const productRegistry: Record<ProductType, new () => Product> = {
  prod1: Product1,
  prod2: Product2,
  prod3: Product3
};

function getProductByType(type: ProductType): Product {
  const ProductConstructor = productRegistry[type];
  // 可选:增加非法类型兜底校验
  if (!ProductConstructor) {
    throw new Error(`无效的产品类型:${type}`);
  }
  return new ProductConstructor();
}

该方案的优势:

  • 无冗余分支判断,代码简洁可维护
  • TypeScript会自动校验注册表是否覆盖了所有合法的ProductType取值,漏写、错写键值会直接报类型错误
  • 后续新增产品类型(比如prod4),只需要新建对应Product类,在注册表中新增一行键值对即可,不需要修改工厂函数逻辑

如果产品类需要传入构造参数,只需要调整注册表的构造函数类型定义即可,比如构造需要传入商品ID参数时,将构造函数类型改为new (id: string) => Product,实例化时传入对应参数即可。

进阶实现:装饰器自动注册

如果产品类型较多,不想手动维护注册表,可以通过类装饰器实现类定义时自动完成注册,进一步减少重复代码:

// 全局注册表
const productRegistry: Record<ProductType, new () => Product> = {} as any;

// 产品注册装饰器
function RegisterProduct(type: ProductType) {
  return function (ProductCtor: new () => Product) {
    productRegistry[type] = ProductCtor;
  };
}

// 类定义时加装饰器即可自动完成注册,无需手动修改注册表
@RegisterProduct('prod1')
class Product1 implements Product {
  readonly type = 'prod1' as const;
  name() {
    return 'Product 1';
  }
}

@RegisterProduct('prod2')
class Product2 implements Product {
  readonly type = 'prod2' as const;
  name() {
    return 'Product 2';
  }
}

@RegisterProduct('prod3')
class Product3 implements Product {
  readonly type = 'prod3' as const;
  name() {
    return 'Product 3';
  }
}

// 工厂函数逻辑和之前完全一致
function getProductByType(type: ProductType): Product {
  const ProductConstructor = productRegistry[type];
  if (!ProductConstructor) {
    throw new Error(`无效的产品类型:${type}`);
  }
  return new ProductConstructor();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 14:39:19