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

如何将TypeScript联合类型映射为具备类型安全的JavaScript Map对象?

实现TypeScript中Modifier名称与对应类型的严格映射

要解决这个键值类型严格匹配的问题,核心是让TypeScript明确每个字符串名称对应的具体类型,而不是只依赖宽泛的联合类型。下面是完整的实现方案:

1. 明确子类型与名称-类型映射

首先我们需要把各个Modifier子类型单独定义(假设你还没明确这些定义,这里补全示例),然后创建一个核心映射类型,把每个名称和对应的类型一一绑定:

// 定义各个Modifier子类型
type RangeModifier = { from: Date; to: Date };
type BeforeModifier = { before: Date };
type AfterModifier = { after: Date };
type BeforeAfterModifier = { before: Date; after: Date };
type DaysOfWeekModifier = { days: number[] };
type FunctionModifier = (date: Date) => boolean;

// 关键:名称到对应类型的映射,这是类型安全的基础
type ModifierTypeMap = {
  'undefined': undefined;
  'Date': Date;
  'RangeModifier': RangeModifier;
  'BeforeModifier': BeforeModifier;
  'AfterModifier': AfterModifier;
  'BeforeAfterModifier': BeforeAfterModifier;
  'DaysOfWeekModifier': DaysOfWeekModifier;
  'FunctionModifier': FunctionModifier;
};

2. 自动推导Modifier联合类型和名称类型

基于上面的映射类型,我们可以自动推导之前定义的Modifier和ModifierNames,避免手动维护重复内容:

// 从映射类型自动生成Modifier联合类型
type Modifier = ModifierTypeMap[keyof ModifierTypeMap];

// 从映射类型的键自动生成ModifierNames类型
type ModifierNames = keyof ModifierTypeMap;

// 如果需要名称数组常量(TypeScript 5.1+支持)
const MODIFIER_NAMES = Object.keys(ModifierTypeMap) as const satisfies readonly ModifierNames[];

3. 创建类型安全的Map

普通的Map<ModifierNames, Modifier>无法约束键值对应关系,因为Modifier是联合类型,TypeScript会允许任何Modifier值和任意键搭配。我们需要重写set和get方法的类型,让它们严格对应映射关系:

// 定义类型安全的Map类型:每个键K对应的值必须是ModifierTypeMap[K]
type TypeSafeModifierMap = {
  set<K extends ModifierNames>(key: K, value: ModifierTypeMap[K]): void;
  get<K extends ModifierNames>(key: K): ModifierTypeMap[K] | undefined;
} & Omit<Map<ModifierNames, Modifier>, 'set' | 'get'>;

// 创建实例并断言类型
const modifierMap: TypeSafeModifierMap = new Map<ModifierNames, Modifier>() as TypeSafeModifierMap;

4. 测试类型安全

现在我们可以验证键值匹配的约束是否生效:

// 测试用例
const rangeModifier: RangeModifier = { from: new Date(), to: new Date() };
const beforeModifier: BeforeModifier = { before: new Date() };

// ✅ 合法操作:键与值类型完全匹配
modifierMap.set('RangeModifier', rangeModifier);
modifierMap.set('BeforeModifier', beforeModifier);
modifierMap.set('Date', new Date());
modifierMap.set('undefined', undefined);

// ❌ 非法操作:键值类型不匹配,TypeScript会直接报错
modifierMap.set('BeforeModifier', rangeModifier);
modifierMap.set('RangeModifier', beforeModifier);

为什么这个方案有效?

  • ModifierTypeMap是整个类型安全的核心,它消除了联合类型的模糊性,让TypeScript明确每个名称对应的具体类型
  • TypeSafeModifierMap通过泛型的set/get方法,强制要求传入的值必须和键对应的类型一致,而不是接受任意的Modifier类型
  • 用& Omit<Map<...>, 'set' | 'get'>保留了原生Map的其他方法(比如has、delete),只重写需要类型约束的方法

内容的提问来源于stack exchange,提问作者Realm Of Code

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 10:32:53