TypeScript中如何结合infer合并校验器类型并实现互斥逻辑?
解决方案与优化方案
问题分析
原代码的核心问题在于规则组移除逻辑的条件分支过于局限,仅能处理元组中特定位置的规则组,导致调用中间位置的规则组方法后,无法正确合并剩余的所有规则组。同时,原逻辑未妥善处理required/noRequired的互斥需求(调用其中一个后需同时禁用两个方法)。
修复后的代码
type CoFormRuleClarity = { email(): any; id(): any; }; type CoFormRuleSize = { min(num: number): any; max(num: number): any; between(min: number, max: number): any; }; type CoFormRuleRequire = { required(): any; noRequired(): any; }; type InvalideFunctionParams = "Please pass the function parameters"; // 通用工具类型:从元组中移除指定类型的所有元素 type RemoveFromTuple<T extends any[], U> = T extends [infer First, ...infer Rest] ? First extends U ? RemoveFromTuple<Rest, U> : [First, ...RemoveFromTuple<Rest, U>] : []; // 包装单个规则组的方法,调用后移除当前规则组并合并剩余规则 type CoFormRuleWarpKeys<T, Raw extends any[]> = { [Key in keyof T]: T[Key] extends (...args: infer P) => any ? (...args: P) => CoFormRuleMerge<RemoveFromTuple<Raw, T>, Raw> : InvalideFunctionParams; }; // 递归合并多个规则组 type CoFormRuleMerge<T extends any[], Raw extends any[]> = T extends [infer First, ...infer Rest] ? CoFormRuleWarpKeys<First, Raw> & CoFormRuleMerge<Rest, Raw> : {}; // 入口类型:合并传入的规则组元组 type CoFormRuleMergeCall<T extends any[]> = CoFormRuleMerge<T, T>; const a: CoFormRuleMergeCall<[ CoFormRuleRequire, CoFormRuleSize, CoFormRuleClarity ]> = {} as any; // 示例1:调用between后,返回CoFormRuleRequire & CoFormRuleClarity const b = a.between(1, 2); // 示例2:调用between后再调用required,返回CoFormRuleClarity const c = a.between(1, 2).required(); // 互斥逻辑测试:调用required后,无法再调用required/noRequired const d = a.required(); // d的类型为CoFormRuleSize & CoFormRuleClarity,无required/noRequired方法
关键修复点
- 通用元组移除工具:新增
RemoveFromTuple类型,能够从任意元组中移除指定类型的元素,替代原代码中局限的位置匹配逻辑,确保不管规则组在元组的哪个位置,调用后都能正确移除。 - 简化规则合并逻辑:重写
CoFormRuleWarpKeys和CoFormRuleMerge,调用任意规则组的方法后,自动移除该规则组并合并剩余所有规则组,天然满足required/noRequired的互斥需求(调用其中一个方法后,整个CoFormRuleRequire规则组被移除,两个方法都不可再调用)。
优化方案
支持细粒度互斥:如果需要规则组内部分方法互斥(而非整个规则组),可新增标记类型定义互斥方法组,例如:
// 定义互斥方法标记 type MutexMethods<T extends string[]> = { __mutexMethods: T }; // 修改CoFormRuleRequire,标记互斥方法 type CoFormRuleRequire = { required(): any; noRequired(): any; } & MutexMethods<["required", "noRequired"]>;再扩展
RemoveFromTuple逻辑,针对标记的互斥方法单独处理,调用其中一个后仅移除该组内的方法,而非整个规则组。增强参数校验:通过条件类型强制方法参数必填,避免运行时参数错误:
type CoFormRuleWarpKeys<T, Raw extends any[]> = { [Key in keyof T]: T[Key] extends (...args: infer P) => any ? P extends [] ? () => CoFormRuleMerge<RemoveFromTuple<Raw, T>, Raw> : (...args: P) => CoFormRuleMerge<RemoveFromTuple<Raw, T>, Raw> : InvalideFunctionParams; };类型推导优化:添加泛型约束,确保传入
CoFormRuleMergeCall的元组仅包含规则组类型,避免非法类型传入:type RuleGroup = Record<string, (...args: any[]) => any>; type CoFormRuleMergeCall<T extends RuleGroup[]> = CoFormRuleMerge<T, T>;
内容的提问来源于stack exchange,提问作者shock cure
相关产品推荐
相关产品推荐

