TypeScript 枚举映射添加参数兼容约束的条件类型报错求解
报错原因
你之前的写法存在两个核心问题:
- 泛型
T定义在了返回函数的签名上,属于调用时才确定的类型参数,TypeScript在你定义mapping赋值的阶段无法推断T的实际类型,自然无法验证返回值是否符合这个延迟计算的条件类型。 - 该写法逻辑存在漏洞:如果调用映射返回的函数时手动传入不匹配的
T,条件类型会直接返回never,和实际返回的枚举值永远无法兼容,因此触发了类型错误。
兼容TS4.2的解决方案
先定义一个预计算的辅助类型,提前找出和每个SourceEnum成员的参数结构完全匹配的TargetEnum值,再基于这个辅助类型定义映射表约束即可,用到的映射类型、索引访问、分布式条件类型都是TS早期版本就支持的特性,完全兼容TS4.2及以上版本。
完整实现代码:
enum SourceEnum { SOURCE_A = 'SOURCE_A', SOURCE_B = 'SOURCE_B' } enum TargetEnum { TARGET_A = 'TARGET_A', TARGET_B = 'TARGET_B', } interface SourceParams { [SourceEnum.SOURCE_A]: { paramA: string }; [SourceEnum.SOURCE_B]: { paramB: number }; } interface TargetParams { [TargetEnum.TARGET_A]: { paramA: string }; [TargetEnum.TARGET_B]: { paramB: number }; } function sourceFn<S extends SourceEnum>(source: S, params: SourceParams[S]) { /* ... */ } function targetFn<T extends TargetEnum>(target: T, params: TargetParams[T]) { /* ... */ } // 辅助类型:自动匹配和Source参数结构兼容的TargetEnum值 type MatchingTarget<K extends SourceEnum> = { [T in TargetEnum]: SourceParams[K] extends TargetParams[T] ? T : never }[TargetEnum] // 约束后的映射表类型 type ConstrainedMapping = { [K in SourceEnum]: () => MatchingTarget<K> } // 赋值不会再触发类型错误 const mapping: ConstrainedMapping = { [SourceEnum.SOURCE_A]: () => TargetEnum.TARGET_A, [SourceEnum.SOURCE_B]: () => TargetEnum.TARGET_B }
效果验证
参数复用的场景完全符合预期,不会报错:
const params = { paramA: 'test' }; sourceFn(SourceEnum.SOURCE_A, params); // 参数可直接复用给targetFn,类型完全匹配 targetFn(mapping[SourceEnum.SOURCE_A](), params);
如果存在多个TargetEnum的参数结构和同一个SourceEnum匹配,MatchingTarget会自动推导为合法的枚举联合类型,返回任意一个匹配的枚举值都符合约束。
内容的提问来源于stack exchange,提问作者Grochni
相关产品推荐
相关产品推荐

