Typescript入参为同键名枚举的函数的理想类型声明写法
TypeScript 枚举转选项数组函数优化方案
你原来的实现存在冗余断言的核心问题是没有通过泛型约束两个入参枚举共享同一键集合,TS 无法推断键的合法性才需要额外的类型断言,优化后的实现如下:
const getOptions = <K extends PropertyKey, L extends Record<K, unknown>, V extends Record<K, unknown>>( LabelEnum: L, ValueEnum: V ): { label: L[K], value: V[K] }[] => { // 仅需要这一次必要断言,原因是TS语言层面固定Object.keys返回值为string[],避免运行时属性和静态类型不一致的边界问题 return (Object.keys(LabelEnum) as K[]).map(key => ({ label: LabelEnum[key], value: ValueEnum[key] })) }
逻辑说明
- 泛型
K是两个枚举共享的键类型,继承自TS内置的PropertyKey(等价于string | number | symbol),覆盖所有合法的对象键类型 - 泛型
L约束为键全是K的对象类型,对应标签枚举入参;泛型V同样约束为键全是K的对象类型,对应值枚举入参,天然保证了两个入参枚举的键集合完全匹配,如果传入键不一致的枚举TS会直接抛出类型错误,符合你对入参的要求 - 返回值直接通过索引访问类型推导对应键的值类型,不需要任何额外断言
适配数字枚举的版本
如果你的场景会用到数字枚举,需要过滤掉数字枚举自带的反向映射键,可以调整为:
const getOptions = <K extends PropertyKey, L extends Record<K, unknown>, V extends Record<K, unknown>>( LabelEnum: L, ValueEnum: V ): { label: L[K], value: V[K] }[] => { return (Object.keys(LabelEnum) as K[]) .filter(key => isNaN(Number(key))) // 过滤数字枚举的反向映射数字键 .map(key => ({ label: LabelEnum[key], value: ValueEnum[key] })) }
内容的提问来源于stack exchange,提问作者Infamous911
相关产品推荐
相关产品推荐

