I have a status = 'DRAFT' | 'READY'
enum field in my form, is it possible to change validation in zod
lib based on value of this field?
// validation passed
{
name: "John",
surname: null,
status: "DRAFT"
}
// validation failed
{
name: "John",
surname: null,
status: "READY"
}
So esentialy if status === "READY"
remove .min(1)
from here
const schema = z.object({
name: z.string(),
surname: z.string().min(1),
status: z.enum(["READY", "DRAFT"])
});
CodePudding user response:
This works
const schema = z.union([
z.object({
name: z.string(),
surname: z.string(),
status: z.literal("DRAFT"),
}),
z.object({
name: z.string(),
surname: z.string().min(1),
status: z.literal("READY"),
}),
]);
CodePudding user response:
The answer you came up with using union
s is possible. An alternative that might yield better types in the future is to take advantage of zod's discriminatedUnion
schema:
// placing shared fields in one place to avoid repetition
const base = z.object({
name: z.string(),
});
const schema = z.discriminatedUnion(
'status',
[
z.object({
status: z.literal("DRAFT"),
surname: z.string(),
}).merge(base),
z.object({
status: z.literal("READY"),
surname: z.string().min(1),
}).merge(base),
],
);
In this case I believe you'll end up with the same inferred types as you would using union
directly, however, this approach is slightly more resilient to other changes you might want to discriminate between. For example if the DRAFT
object allowed surname
to be optional
then using the discriminated union would me that you could refine to non-optional types if status
is "READY"
.
With union
definition, the type for surname
in that example would always be string | undefined
regardless of the value of status
.