TypeScript如何编写类型安全的通用函数将枚举值转换为字符串
类型安全的枚举转字符串实现方案
问题根源
原实现第二个参数固定标注为number,与第一个传入的枚举对象类型没有任何绑定关系,TS无法校验两者的匹配性:所有数字类型值(包括其他枚举的成员、任意普通数字)都能通过类型检查,自然无法拦截错误传参。
正确实现
通过泛型绑定两个参数的类型关联,强制第二个参数必须是第一个传入枚举的合法成员值,即可实现编译期校验:
// 提取枚举的合法成员值类型,过滤数字枚举反向映射键的干扰 type EnumMember<T> = T[keyof { [K in keyof T as K extends `${number}` ? never : K] }] function enumToString<T extends Record<string | number, string | number>>( myenum: T, myenumvalue: EnumMember<T> ): string { const reverseValue = myenum[myenumvalue] // 数字枚举走反向映射返回键名,字符串枚举直接返回成员值本身 return typeof reverseValue === 'string' ? reverseValue : (myenumvalue as string) }
效果验证
- 合法调用可正常通过类型检查:
enum MyEnum { TheA, TheB, TheC } // strValue运行时值为"TheA",类型推导为string const strValue = enumToString(MyEnum, MyEnum.TheA)
- 跨枚举传参的错误调用会被TS直接拦截,无法通过编译:
enum TotallyDifferentEnum { X, Y } // 此处TS抛出类型不匹配错误 const errorValue = enumToString(TotallyDifferentEnum, MyEnum.TheA)
实现说明
- 泛型
T会自动推导第一个参数传入的枚举对象类型 EnumMember<T>工具类型会过滤掉数字枚举自带的数字格式反向键,只提取枚举正向定义的合法成员值类型,从类型层面强制两个参数的关联关系- 实现同时兼容数字枚举、字符串枚举两类场景:数字枚举通过内置反向映射拿到对应的键名字符串,字符串枚举因为没有反向映射,直接返回成员值本身即可
内容的提问来源于stack exchange,提问作者Alex N
相关产品推荐
相关产品推荐

