如何用Zod验证email与reemail字段值一致?
Zod 实现邮箱重复验证的方案
方法一:修复你的 superRefine 写法
你的代码逻辑本身是正确的,大概率是验证触发方式的问题导致没生效。确保你通过 parse 或 safeParse 方法执行验证,以下是完整可运行的示例:
import { z } from "zod"; export const validationSchema = z.object({ email: z.string().email({ message: "请输入有效的邮箱地址。" }).min(1, "此字段为必填项。"), reemail: z.string().min(1, "此字段为必填项。"), }).superRefine((data, ctx) => { if (data.email !== data.reemail) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: "两次输入的邮箱不匹配。", path: ["reemail"] // 将错误标记在重复输入的邮箱字段上 }); } }); // 验证测试 const validInput = { email: "test@example.com", reemail: "test@example.com" }; console.log(validationSchema.safeParse(validInput)); // 输出成功结果 const invalidInput = { email: "test@example.com", reemail: "wrong@example.com" }; console.log(validationSchema.safeParse(invalidInput)); // 输出包含reemail字段错误的结果
方法二:字段内直接依赖验证(更简洁)
如果你想贴近 Yup oneOf 的使用习惯,可以在 reemail 字段内直接引用 email 的值,无需用到 superRefine:
方式1:使用 refine 结合父级字段
import { z } from "zod"; export const validationSchema = z.object({ email: z.string().email({ message: "请输入有效的邮箱地址。" }).min(1, "此字段为必填项。"), reemail: z.string() .min(1, "此字段为必填项。") .refine((val, ctx) => val === ctx.parent.email, { message: "两次输入的邮箱不匹配。" }) });
方式2:使用 oneOf + z.lazy(贴近Yup写法)
通过 z.lazy 解决循环引用问题,让 reemail 匹配 email 的值:
import { z } from "zod"; export const validationSchema = z.object({ email: z.string().email({ message: "请输入有效的邮箱地址。" }).min(1, "此字段为必填项。"), reemail: z.string() .min(1, "此字段为必填项。") .oneOf([z.lazy(() => validationSchema.shape.email)], { message: "两次输入的邮箱不匹配。" }) });
方案对比
superRefine适合多字段联动验证、需要添加多个自定义错误的复杂场景;- 字段内的
refine写法更简洁,适合单一字段依赖父级字段的简单验证; oneOf+z.lazy的写法最贴近你之前使用 Yup 的习惯,逻辑直观。
内容的提问来源于stack exchange,提问作者ahols
相关产品推荐
相关产品推荐

