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

如何将Yup的条件必填校验逻辑转换为Zod实现?

Zod实现条件必填字段的简洁方案

需求说明

当is_change_part的值为'Yes'时,barcode_old为必填项;默认情况下该字段为可选。

原Yup实现代码

const stringRequired = yup.string().required();

export const validation = yup.object().shape({
    serial_number: stringRequired,
    barcode_old: yup.string().when('is_change_part', {
         is: (isChangePart: string) => isChangePart === 'Yes',
         then: stringRequired,
    }),
    category: stringRequired,
    sub_category: stringRequired,
    is_change_part: stringRequired
});

你当前的Zod尝试(可行但繁琐)

const stringRequired = z.string().min(1);

export const Schema = z
  .object({
    serial_number: stringRequired,
    barcode_old: z.string().optional(),
    is_change_part: stringRequired,
    category: stringRequired,
    sub_category: stringRequired,
  })
  .superRefine((val, ctx) => { 
    // 当is_change_part为'Yes'时,barcode_old必填
    if (val.is_change_part === 'Yes' && val.barcode_old === undefined) {
      ctx.addIssue({
        code: 'custom',
        message: '必填项',
        path: ['barcode_old'],
      });
    }
  });

更简洁的Zod实现方式

方式一:精简版refine写法(推荐)

这种写法最贴近Yup的when逻辑,把跨字段校验逻辑浓缩为一行:

const stringRequired = z.string().min(1, '必填项');

export const Schema = z.object({
  serial_number: stringRequired,
  barcode_old: z.string().optional(),
  is_change_part: stringRequired,
  category: stringRequired,
  sub_category: stringRequired,
}).refine(
  (val) => val.is_change_part !== 'Yes' || !!val.barcode_old,
  {
    message: '必填项',
    path: ['barcode_old'],
  }
);

逻辑说明:当is_change_part不等于'Yes'时无需校验;如果等于'Yes',则barcode_old必须存在且不为空字符串(!!val.barcode_old和stringRequired的min(1)校验逻辑一致)。

方式二:联合类型拆分场景(更直观)

通过联合类型明确区分两种状态的结构,适合复杂多场景的校验需求:

const stringRequired = z.string().min(1, '必填项');

// 定义「更换部件」场景的schema
const ChangePartYesSchema = z.object({
  serial_number: stringRequired,
  barcode_old: stringRequired,
  is_change_part: z.literal('Yes'),
  category: stringRequired,
  sub_category: stringRequired,
});

// 定义「不更换部件」场景的schema
const ChangePartNoSchema = z.object({
  serial_number: stringRequired,
  barcode_old: z.string().optional(),
  is_change_part: z.string().not(z.literal('Yes')),
  category: stringRequired,
  sub_category: stringRequired,
});

export const Schema = z.union([ChangePartYesSchema, ChangePartNoSchema]);

这种写法能让校验逻辑更清晰,Zod会自动根据is_change_part的值匹配对应schema,错误提示也会更精准。

内容的提问来源于stack exchange,提问作者muhfaridzia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 09:40:16