基于null返回为成功标识的回调链类型推断实现问题
实现
composeValidators 函数的方案 1. 定义基础类型
先明确验证器和错误的类型,兼容两种验证器返回格式:
// 错误类型:包含简单验证器转换后的统一格式 type ValidationError = { simple: true } | Record<string, unknown>; // 通用验证器类型:输入类型T,验证通过时可窄化为子类型U,返回值支持布尔值/错误对象/null type Validator<T, U extends T = T> = (value: T) => ValidationError | null | boolean;
2. 实现类型流转的核心工具类型
通过TypeScript泛型和条件类型,自动提取验证通过后的窄化类型:
// 提取单个验证器通过后的窄化类型 type ValidatorPassType<V> = V extends Validator<infer T, infer U> ? U : never; // 取数组最后一个元素的类型 type Last<T extends readonly any[]> = T extends [...infer _, infer L] ? L : never; // 组合验证器的最终类型:自动流转输入类型,输出最终窄化后的验证器 type ComposedValidator<Validators extends readonly Validator<any, any>[]> = Validators extends [] ? Validator<unknown> : Validators extends [infer First, ...infer Rest] ? Rest extends Validator<any, any>[] ? Validator<Parameters<First>[0], ValidatorPassType<Last<Rest>>> : never : never;
3. 实现composeValidators函数
处理验证器串联逻辑,自动转换简单验证器返回值,同时实现类型流转:
function composeValidators<Validators extends readonly Validator<any, any>[]>( ...validators: Validators ): ComposedValidator<Validators> { return (value: unknown) => { let currentValue: unknown = value; for (const validator of validators) { const result = validator(currentValue as Parameters<typeof validator>[0]); // 处理布尔值返回的简单验证器 if (typeof result === 'boolean') { if (!result) return { simple: true }; continue; } // 验证不通过,直接返回错误 if (result !== null) { return result; } // 验证通过,传递窄化后的值给下一个验证器 currentValue = value; } return null; } as ComposedValidator<Validators>; }
4. 结合Angular信号表单field的使用示例
无需手动检查非空,类型自动随验证通过逐步窄化:
// 示例验证器 const required = <T>(value: T | null | undefined): value is T => { return value != null; }; const minLength = (length: number) => (value: string): ValidationError | null => { return value.length >= length ? null : { minLength: { requiredLength: length, actualLength: value.length } }; }; const isEmail = (value: string): ValidationError | null => { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(value) ? null : { email: true }; }; // 组合验证器:required通过后,后续自动获得非空string类型 const emailFieldValidator = composeValidators( required, minLength(5), isEmail ); // Angular信号表单field调用 const emailField = field<string | null>({ initialValue: null, validators: emailFieldValidator });
5. 核心特性说明
- 自动类型窄化:前序验证器通过(返回
null/true)后,后续验证器的输入类型自动更新为窄化后的类型 - 兼容简单验证器:返回
false的验证器会自动转为{ simple: true }错误对象 - 短路逻辑:任意验证器不通过时,立即终止并返回对应错误
内容的提问来源于stack exchange,提问作者Alessandro Caramia
相关产品推荐
相关产品推荐

