如何根据subject字段值在Zod中条件验证role字段?
解决Zod条件验证问题:仅当subject为1时验证role字段
你可以通过两种方式实现这个需求:
方法一:使用Union类型拆分场景
把schema拆分成两种情况的联合类型,分别处理subject为1和不为1的场景:
// 定义基础字段的schema(不含role) const baseSchema = z.object({ subject: z.number().default(0), gender: z.object({ owner: z.number(), stranger: z.number().array().min(1), }), age: z.object({ owner: z.number(), stranger: z.number().array().min(1), }), }); // subject为1时,强制验证role的结构 const subject1Schema = baseSchema.extend({ subject: z.literal(1), role: z.object({ owner: z.number(), stranger: z.number(), }), }); // subject不为1时,role可以是任意值(允许不存在则加.optional()) const otherSubjectSchema = baseSchema.extend({ subject: z.number().not(z.literal(1)), role: z.unknown().optional(), }); // 合并为最终schema const schema = z.union([subject1Schema, otherSubjectSchema]);
方法二:在整个Object上使用refine
直接在根object上调用refine,这样就能访问所有字段,根据subject的值决定是否验证role:
const schema = z.object({ subject: z.number().default(0), gender: z.object({ owner: z.number(), stranger: z.number().array().min(1), }), age: z.object({ owner: z.number(), stranger: z.number().array().min(1), }), role: z.unknown(), // 先允许role为任意类型 }).refine((data) => { // subject不为1时直接通过验证 if (data.subject !== 1) return true; // subject为1时,验证role的结构 const roleValidator = z.object({ owner: z.number(), stranger: z.number(), }); return roleValidator.safeParse(data.role).success; }, { message: "当subject为1时,role必须包含数字类型的owner和stranger字段", path: ["role"], // 让错误提示指向role字段 });
为什么之前的refine没用?
你之前尝试的refine应该是单独给某个字段调用的,这种情况下只能访问当前字段的值,无法获取其他字段(比如subject)。只有在整个object schema上调用refine,才能拿到完整的data对象,从而实现跨字段的条件验证。
内容的提问来源于stack exchange,提问作者Witcher
相关产品推荐
相关产品推荐

