I have a zod schema like this:
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.string(),
lastname: z.string(),
documentType: zDocumentationType,
documentValue: z.string(),
email: z.string().email(),
phone: z.string().regex(/^\d{9}$/)
})
}).refine((data) => .....)
Is it possible to validate tutor object is required only if birthdate is under 18 ? Because if member is +18 this fields are not needed.
I know how to validate a field depending of another one in refine function, but I don't know how to validate and entire object...
EXAMPLE:
tutor
has to be filled and passing zod tutor object validationAfter many tries I got what I want with z.union
between object
and undefined
and super refine.
Here is my code. Hope it helps someone in future.
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.union([
z.object({
name: zTutorString,
lastname: zTutorString,
document: zTutorString,
email: zTutorString.email(),
phone: zTutorString.regex(/^\d{9}$/)
}),
z.undefined()
])
})
.superRefine((data, ctx) => {
const validation =
data.birthdate.getFullYear() + 18 < new Date().getFullYear() ||
(data.birthdate.getFullYear() + 18 > new Date().getFullYear() && data.tutor !== undefined)
if (!validation) {
tutorFields.forEach((field) => {
if (!data.tutor || (data.tutor && !data.tutor[field as keyof typeof data.tutor])) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: i18n.t('validation.required_tutor'),
path: ['tutor', field]
})
}
})
}
})