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

如何在Zod中编写Refine规则:允许数值为null且非空时校验大小

解决Zod refine在字段为null时仍触发校验的问题

你的问题出在humidity和maxHumidity对应的refine逻辑上:当前条件只有当两个字段都不为null且humidity < maxHumidity时才返回true,而当其中一个或两个为null时,整个表达式会返回false,Zod会将false判定为校验失败,所以即使两个字段都是null也会触发错误提示。

要实现「仅当两个数值均不为null时才校验大小,否则允许为空」的需求,需要调整refine的逻辑:只要两个字段中有一个是null,就直接通过校验;只有当两个都有值时,才检查humidity是否小于maxHumidity。

修改后的完整代码如下:

type formData = {
  name: string;
  password: number;
  confirmPassword: number;
  humidity: number | null;
  maxHumidity: number | null;
};

const schema: ZodType<formData> = z
  .object({
    name: z.string().min(1).max(10),
    password: z.number().min(0).max(10),
    confirmPassword: z.number().min(0).max(10),
    humidity: z.number().min(0).max(10).nullable(),
    maxHumidity: z.number().min(0).max(10).nullable(),
  })
  .refine((data) => data.password > data.confirmPassword, {
    message: "密码必须大于确认密码",
    path: ["password"],
  })
  .refine(
    (data) => 
      // 逻辑:要么至少一个字段为null(跳过校验),要么两个都有值且满足大小关系
      (data.humidity === null || data.maxHumidity === null) || 
      data.humidity < data.maxHumidity,
    {
      message: "最大湿度必须大于湿度",
      path: ["maxHumidity"],
    }
  );

const {
  register,
  handleSubmit,
  reset,
  formState: { errors },
} = useForm<formData>({
  resolver: zodResolver(schema),
  defaultValues: { humidity: null, maxHumidity: null },
});

关键逻辑说明

  • 新的refine条件拆为两部分:
    1. (data.humidity === null || data.maxHumidity === null):只要其中一个字段为null,直接返回true,允许通过校验
    2. data.humidity < data.maxHumidity:只有当两个字段都不为null时,才执行大小校验,满足则返回true,否则返回false触发错误

另外顺便修正了你原代码里的错误提示文案(把“确认密码”改为“湿度”),避免混淆。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 08:02:49