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:
- { birthdate: ’20/02/2015′} -> ALL Fields in
tutor
has to be filled and passing zod tutor object validation - {birthdate: ’09/05/1988′ } -> Tutor object is undefined and returns true.
2
Answers
After many tries I got what I want with
z.union
betweenobject
andundefined
and super refine.Here is my code. Hope it helps someone in future.
You can use a
superRefine
call to add issues to the overall object. For example:Note that going from the
Date
object to their age in years is potentially non-trivial, so I’ve left that as an exercise for the reader.The main trick is to make the tutor field optional, and then to use the refine to say, "no actually it must be defined if the user is over 18".
A note on types
Unfortunately, this approach does not give you any firmer type guarantees once you know that the user is under 18. If you want the type system to track this for you, you could split the types along the
birthdate
and usez.brand
to attach that additional information, but it may be more trouble than it’s worth.