You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 06:14:53