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

如何使用Yup实现数组的条件验证?

用Yup实现基于状态的数组条件验证

我正尝试使用Yup实现数组的条件验证,但遇到了困难。表单定义如下:

enum Status {
 RED = 'Red',
 GREEN = 'Green',
 YELLOW = 'Yellow',
}

interface MyField {
  fieldType: MyFieldType;
  fieldValue: string;
}

enum MyFieldType {
  FIELD_TYPE_1 = '1',
  FIELD_TYPE_2 = '2',
  FIELD_TYPE_3 = '3',
}

const validationSchema = yup.object({
    status: yup.mixed<Status>().required(),
    fields: yup.array().of(yup.mixed<MyField>()).required()
});

需求是fields数组要根据status字段的值进行条件验证,需包含特定fieldType的元素:

  • 当status === Status.RED时,数组必须包含一个fieldType为MyFieldType.FIELD_TYPE_1的元素,且该元素的fieldValue不能为空
  • 当status === Status.GREEN时,数组必须同时包含fieldType为MyFieldType.FIELD_TYPE_2和MyFieldType.FIELD_TYPE_3的元素,且这两个元素的fieldValue都不能为空
  • 其他状态可自定义组合规则

我知道Yup的when方法,但不确定如何针对该场景正确使用,目前的框架如下:

fields: yup.array().of(yup.mixed<MyField>()).when('status', {
  is: (status: Status) => status === Status.GREEN,
  then: yup.array().of(// 不知道如何验证数组包含指定MyFieldType且对应fieldValue非空 )
}

完整实现方案

要实现这种数组的条件验证,结合Yup的when方法、test自定义验证以及数组约束规则即可完成。以下是完整的验证Schema:

import * as yup from 'yup';

// 定义单个MyField的通用验证规则
const myFieldSchema = yup.object<MyField>().shape({
  fieldType: yup.mixed<MyFieldType>().oneOf(Object.values(MyFieldType)).required(),
  fieldValue: yup.string().trim().required()
});

const validationSchema = yup.object({
  status: yup.mixed<Status>().oneOf(Object.values(Status)).required(),
  fields: yup.array().of(myFieldSchema).required()
    // RED状态下的验证规则
    .when('status', {
      is: Status.RED,
      then: schema => schema.test(
        'has-valid-field-type-1',
        '必须包含fieldType为1的字段且值不为空',
        (fields) => {
          return fields.some(field => 
            field.fieldType === MyFieldType.FIELD_TYPE_1 && 
            yup.string().trim().required().isValidSync(field.fieldValue)
          );
        }
      )
    })
    // GREEN状态下的验证规则
    .when('status', {
      is: Status.GREEN,
      then: schema => schema.test(
        'has-valid-field-type-2-and-3',
        '必须同时包含fieldType为2和3的字段且值不为空',
        (fields) => {
          const hasValidType2 = fields.some(field => 
            field.fieldType === MyFieldType.FIELD_TYPE_2 && 
            yup.string().trim().required().isValidSync(field.fieldValue)
          );
          const hasValidType3 = fields.some(field => 
            field.fieldType === MyFieldType.FIELD_TYPE_3 && 
            yup.string().trim().required().isValidSync(field.fieldValue)
          );
          return hasValidType2 && hasValidType3;
        }
      )
    })
    // YELLOW状态下的自定义规则(示例)
    .when('status', {
      is: Status.YELLOW,
      then: schema => schema.test(
        'yellow-status-rule',
        'YELLOW状态下的自定义验证提示',
        (fields) => {
          // 替换为实际需要的验证逻辑
          return fields.length >= 1;
        }
      )
    })
});

关键逻辑说明

  1. 单个字段校验复用:先定义myFieldSchema统一验证数组中每个元素的合法性,确保fieldType是枚举有效值,fieldValue是非空字符串,避免重复编写校验逻辑。
  2. 链式when调用:针对不同的status值,链式调用when方法添加对应的数组级校验规则,互不干扰。
  3. 自定义test校验:通过test方法编写数组的全局校验逻辑,使用some方法检查数组中是否存在符合要求的元素,同时复用Yup内置的字符串验证确保fieldValue有效。
  4. 错误提示自定义:每个test的第二个参数是自定义错误文案,让用户能清晰理解错误原因。

可选优化:复用校验逻辑

如果多个状态需要重复“检查数组包含指定fieldType且值有效”的逻辑,可以抽成工具函数:

const hasValidTargetField = (fields: MyField[], targetType: MyFieldType) => {
  return fields.some(field => 
    field.fieldType === targetType && 
    yup.string().trim().required().isValidSync(field.fieldValue)
  );
};

// 调用示例:
// return hasValidTargetField(fields, MyFieldType.FIELD_TYPE_1);
// return hasValidTargetField(fields, MyFieldType.FIELD_TYPE_2) && hasValidTargetField(fields, MyFieldType.FIELD_TYPE_3);

内容的提问来源于stack exchange,提问作者Franjo Pintarić

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 06:25:06