TypeScript能否基于基础枚举派生首字母大写的成员枚举?
如何从基础枚举派生大小写不同的枚举?
需求场景
我们正在构建一项服务,流程如下:
- 接收输入,例如
{titleDe: 'Lorem', titleFr: 'Ipsum'} - 返回目标语言(如'de')对应的所有带后缀属性
- 输出结果:
{title: 'Lorem'}
当前实现的痛点
目前我们用两个枚举分别处理语言校验和后缀匹配:
语言校验枚举
export enum Language { DE = 'de', IT = 'it', FR = 'fr', EN = 'en', }
语言后缀枚举
export enum LanguageSuffix { DE = 'De', IT = 'It', FR = 'Fr', EN = 'En', }
这两个枚举仅成员值的大小写不同,需要重复维护,非常麻烦。之前尝试过enum LanguageSuffix { DE = Capitalize<Language> },但因为类型和值不匹配无法生效,想找个办法从基础枚举直接派生另一个。
可行解决方案
1. 用对象+类型别名替代枚举(推荐)
TypeScript的枚举本质上是对象,我们可以先定义基础的语言配置对象,再自动派生后缀对象,同时生成对应的类型:
// 基础语言配置,只需要维护这一个 const Language = { DE: 'de', IT: 'it', FR: 'fr', EN: 'en', } as const; // 自动派生后缀对象 const LanguageSuffix = Object.fromEntries( Object.entries(Language).map(([key, value]) => [ key, value.charAt(0).toUpperCase() + value.slice(1) ]) ) as { [K in keyof typeof Language]: Capitalize<typeof Language[K]> }; // 生成对应的类型别名,保留类型校验能力 type Language = typeof Language[keyof typeof Language]; type LanguageSuffix = typeof LanguageSuffix[keyof typeof LanguageSuffix];
这样只需要维护Language对象,LanguageSuffix会自动同步更新,同时完全保留原有的类型校验功能。
2. 保留枚举+工具函数动态生成后缀
如果一定要用枚举形式,可以只维护Language枚举,通过工具函数动态转换得到后缀:
export enum Language { DE = 'de', IT = 'it', FR = 'fr', EN = 'en', } // 工具函数:把语言标识转换为对应的后缀 function getLanguageSuffix(lang: Language): Capitalize<Language> { return (lang.charAt(0).toUpperCase() + lang.slice(1)) as Capitalize<Language>; } // 使用示例 const deSuffix = getLanguageSuffix(Language.DE); // 类型为'De',值也是'De'
这种方式不需要维护第二个枚举,直接通过函数转换就能得到正确的后缀,同时Capitalize工具类型保证了返回值的类型正确性。
3. 利用TypeScript 5.0+的枚举合并特性
如果你的项目使用TypeScript 5.0及以上版本,可以用枚举合并来派生:
export enum Language { DE = 'de', IT = 'it', FR = 'fr', EN = 'en', } // 先声明空的后缀枚举 export enum LanguageSuffix {} // 动态赋值,从Language枚举派生后缀 Object.assign(LanguageSuffix, Object.fromEntries( Object.entries(Language).map(([key, value]) => [ key, value.charAt(0).toUpperCase() + value.slice(1) ]) )); // 为后缀枚举添加类型声明 type LanguageSuffix = Capitalize<Language>;
这种方式保留了枚举的语法形式,同时避免了手动重复编写成员。
内容的提问来源于stack exchange,提问作者sandrooco
相关产品推荐
相关产品推荐

