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

如何为Map/对象定义TypeScript类型以强制包含所有GradeLevel枚举键

如何在TypeScript中强制Map/对象包含枚举的所有键

针对对象的解决方案

你提到的Record类型其实完全可以适配数字枚举场景,TypeScript支持将数字枚举值作为对象的键进行类型约束,只要声明时明确指定类型,就能强制要求包含所有枚举键:

首先补全示例中缺失的EmojiCode枚举:

enum EmojiCode {
  CONFOUNDED_FACE = '😖',
  SLIGHTLY_FROWNING_FACE = '😕',
  SLIGHTLY_SMILING_FACE = '🙂',
  SMILING_FACE_WITH_SMILING_EYES = '😊',
  SMILING_FACE_WITH_HEART_EYES = '😍'
}

enum GradeLevel {
  ONE = 1,
  TWO = 2,
  THREE = 3,
  FOUR = 4,
  FIVE = 5
}

然后用Record<GradeLevel, EmojiCode>约束对象:

// 正确:包含所有GradeLevel枚举键
const GRADE_EMOJI_OBJECT: Record<GradeLevel, EmojiCode> = {
  [GradeLevel.ONE]: EmojiCode.CONFOUNDED_FACE,
  [GradeLevel.TWO]: EmojiCode.SLIGHTLY_FROWNING_FACE,
  [GradeLevel.THREE]: EmojiCode.SLIGHTLY_SMILING_FACE,
  [GradeLevel.FOUR]: EmojiCode.SMILING_FACE_WITH_SMILING_EYES,
  [GradeLevel.FIVE]: EmojiCode.SMILING_FACE_WITH_HEART_EYES
};

// 错误:遗漏GradeLevel.FIVE,TypeScript会直接抛出类型错误
const GRADE_EMOJI_OBJECT_2: Record<GradeLevel, EmojiCode> = {
  [GradeLevel.ONE]: EmojiCode.CONFOUNDED_FACE,
  [GradeLevel.TWO]: EmojiCode.SLIGHTLY_FROWNING_FACE,
  [GradeLevel.THREE]: EmojiCode.SLIGHTLY_SMILING_FACE,
  [GradeLevel.FOUR]: EmojiCode.SMILING_FACE_WITH_SMILING_EYES,
};

针对Map的解决方案

Map的默认类型Map<GradeLevel, EmojiCode>只约束键值类型,不会检查是否包含所有枚举键。我们可以通过自定义工具类型或工厂函数来实现强制检查:

方法1:使用类型断言+工具类型

先定义一个工具类型,要求数组必须包含每个枚举键对应的条目:

type RequiredMapEntries<K extends string | number | symbol, V> = {
  [Key in K]: [Key, V]
}[K][]

然后在创建Map时用这个类型约束构造参数:

// 正确:包含所有条目
const GRADE_EMOJI_MAP = new Map<GradeLevel, EmojiCode>(
  [
    [GradeLevel.ONE, EmojiCode.CONFOUNDED_FACE],
    [GradeLevel.TWO, EmojiCode.SLIGHTLY_FROWNING_FACE],
    [GradeLevel.THREE, EmojiCode.SLIGHTLY_SMILING_FACE],
    [GradeLevel.FOUR, EmojiCode.SMILING_FACE_WITH_SMILING_EYES],
    [GradeLevel.FIVE, EmojiCode.SMILING_FACE_WITH_HEART_EYES]
  ] as RequiredMapEntries<GradeLevel, EmojiCode>
);

// 错误:遗漏GradeLevel.FIVE,TypeScript会报错
const GRADE_EMOJI_MAP_2 = new Map<GradeLevel, EmojiCode>(
  [
    [GradeLevel.ONE, EmojiCode.CONFOUNDED_FACE],
    [GradeLevel.TWO, EmojiCode.SLIGHTLY_FROWNING_FACE],
    [GradeLevel.THREE, EmojiCode.SLIGHTLY_SMILING_FACE],
    [GradeLevel.FOUR, EmojiCode.SMILING_FACE_WITH_SMILING_EYES],
  ] as RequiredMapEntries<GradeLevel, EmojiCode>
);

方法2:封装工厂函数(更优雅)

用函数封装Map的创建逻辑,自动完成类型检查:

function createCompleteMap<K extends string | number | symbol, V>(entries: RequiredMapEntries<K, V>): Map<K, V> {
  return new Map(entries);
}

// 正确:所有条目齐全
const GRADE_EMOJI_MAP = createCompleteMap<GradeLevel, EmojiCode>([
  [GradeLevel.ONE, EmojiCode.CONFOUNDED_FACE],
  [GradeLevel.TWO, EmojiCode.SLIGHTLY_FROWNING_FACE],
  [GradeLevel.THREE, EmojiCode.SLIGHTLY_SMILING_FACE],
  [GradeLevel.FOUR, EmojiCode.SMILING_FACE_WITH_SMILING_EYES],
  [GradeLevel.FIVE, EmojiCode.SMILING_FACE_WITH_HEART_EYES]
]);

// 错误:遗漏条目,TypeScript直接报错
const GRADE_EMOJI_MAP_2 = createCompleteMap<GradeLevel, EmojiCode>([
  [GradeLevel.ONE, EmojiCode.CONFOUNDED_FACE],
  [GradeLevel.TWO, EmojiCode.SLIGHTLY_FROWNING_FACE],
  [GradeLevel.THREE, EmojiCode.SLIGHTLY_SMILING_FACE],
  [GradeLevel.FOUR, EmojiCode.SMILING_FACE_WITH_SMILING_EYES],
]);

原理说明

RequiredMapEntries类型会遍历枚举的每个键,生成对应的[Key, V]条目类型,再将所有条目类型组合成联合数组。如果数组中缺少任何一个枚举键对应的条目,TypeScript会检测到类型不匹配并抛出错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 13:30:18