TypeScript枚举遍历:仅用枚举键创建Skill实例并添加至数组
解决枚举遍历与反向映射问题
首先,我注意到你当前的枚举写法用了<any>类型断言,这会让TypeScript为这个字符串值的枚举生成双向映射(也就是你提到的反向映射),但这也导致for...in遍历时会同时拿到枚举的原始键(如ACROBATICS)和反向映射的键(如"Acrobatics")。我们可以分两步解决你的需求:只使用枚举键创建Skill实例,同时保留反向映射功能。
方案一:使用标准字符串枚举 + 手动创建反向映射
TypeScript的字符串枚举默认不会生成反向映射,所以我们可以先修正枚举的写法,然后手动构建反向映射对象,这样既干净又能满足需求:
// 标准字符串枚举,无自动反向映射 enum eSkills { ACROBATICS = "Acrobatics", APPRAISE = "Appraise", BLUFF = "Bluff", CLIMB = "Climb", CRAFT = "Craft" } class Skill { constructor(name: eSkills) { this.name = name; } name: eSkills; } // 手动创建反向映射:通过技能显示名称获取枚举键 const eSkillsReverse: Record<eSkills, keyof typeof eSkills> = Object.fromEntries( Object.entries(eSkills).map(([key, value]) => [value, key]) ) as Record<eSkills, keyof typeof eSkills>; let skills: Skill[] = []; // 遍历枚举的原始键,创建Skill实例 for (const skillKey in eSkills) { const skillEnumValue = eSkills[skillKey as keyof typeof eSkills]; skills.push(new Skill(skillEnumValue)); } // 测试反向映射 console.log(eSkillsReverse["Acrobatics"]); // 输出 "ACROBATICS"
方案二:保留现有枚举写法,过滤反向映射键
如果你想保留当前使用<any>的枚举写法(它会自动生成双向映射),那么在遍历时需要过滤掉反向映射的键。我们可以通过判断键是否等于其大写形式(因为你的枚举键都是大写,反向映射的键是首字母大写的显示名称)来过滤:
enum eSkills { ACROBATICS = <any>"Acrobatics", APPRAISE = <any>"Appraise", BLUFF = <any>"Bluff", CLIMB = <any>"Climb", CRAFT = <any>"Craft" } class Skill { constructor(name: eSkills) { this.name = name; } name: eSkills; } let skills: Skill[] = []; for (let skill in eSkills) { // 过滤掉反向映射的键(仅保留大写的枚举原始键) if (skill === skill.toUpperCase()) { skills.push(new Skill(eSkills[skill] as eSkills)); } } // 测试自动生成的反向映射 console.log(eSkills["Acrobatics"]); // 输出 "ACROBATICS"
小提示
- 方案一的标准字符串枚举更符合TypeScript的最佳实践,手动创建的反向映射也更可控,避免了
<any>带来的类型不安全。 - 方案二的过滤逻辑依赖枚举键的命名规范(全大写),如果后续枚举键命名变化,需要同步调整过滤条件。
内容的提问来源于stack exchange,提问作者user9564808
相关产品推荐
相关产品推荐

