我有一个像这样的zod模式:
export const memberSchema = z
.object({
name: z.string().min(3),
lastname: z.string().min(3),
nationality: zCountries,
birthdate: z.date(),
email: z.string().email(),
tutor: z
.object({
name: z.union([z.string(), z.undefined()]),
lastname: z.union([z.string(), z.undefined()]),
documentType: z.union([zDocumentationType, z.undefined()]),
documentValue: z.union([z.string(), z.undefined()]),
email: z.union([z.string().email(), z.undefined()]),
phone: z.union([z.string().regex(/^\d{9}$/), z.undefined()])
})
}).refine((data) => .....)
是否可以仅在出生日期未满 18 岁的情况下验证导师对象? 因为如果成员是 +18,则不需要此字段。
我知道如何在精炼函数中根据另一个字段来验证一个字段,但我不知道如何验证整个对象...
您可以使用
superRefine
调用将问题添加到整个对象。例如:
export const memberSchema = z
.object({
name: z.string().min(3),
lastname: z.string().min(3),
nationality: zCountries,
birthdate: z.date(),
email: z.string().email(),
tutor: tutorSchema.optional(),
})
.superRefine((obj, ctx) => {
const ageInYears = getAgeInYears(obj.birthdate);
if (ageInYears < 18 && obj.tutor === undefined) {
ctx.addIssue({
code: "custom",
message: "Members under the age of 18 must have a tutor",
});
}
});
console.log(
memberSchema.safeParse({
name: "Test",
lastname: "Testerson",
nationality: "USA",
birthdate: new Date("2010-1-1"), // Some date less than 18 years ago
email: "[email protected]",
})
); // Logs failure with custom message
console.log(
memberSchema.safeParse({
name: "Test",
lastname: "Testerson",
nationality: "USA",
birthdate: new Date("2010-1-1"), // Some date less than 18 years ago
email: "[email protected]",
tutor: {
name: "Tutor",
lastname: "Some tutor",
phone: undefined,
email: undefined,
documentType: undefined,
documentValue: undefined,
},
})
); // Logs success
请注意,从
Date
对象到其年龄(以年为单位)可能并不简单,因此我将其作为练习留给读者。
主要技巧是使导师字段可选,然后使用精炼说,“不,实际上,如果用户超过 18 岁,则必须定义它”。
不幸的是,一旦您知道用户未满 18 岁,这种方法就不会为您提供任何更可靠的类型保证。如果您希望类型系统为您跟踪这一点,您可以沿着
birthdate
拆分类型并使用 z.brand
附加附加信息,但这可能比它的价值更麻烦。