Reputation: 679
I have the properties startDate
and endDate
in a Zod schema. I'd like to verify that either:
I.e. if only startDate
or only endDate
is set, parsing will fail.
The schema looks like:
export const MediumSchema = z.object({
ImageSetID: z.number().int().positive(),
...
CampaignStartDate: z.date().nullable(),
CampaignEndDate: z.date().nullable(),
Url: z.string().url().transform((url) => new URL(url)),
CDNUrl: z.string().url().transform((url) => new URL(url))
});
How do I achieve this?
Upvotes: 4
Views: 4539
Reputation: 9826
You can use union
or the built in or
method to union the two possible schemas you expect. For example:
import { z } from 'zod';
const schema = z.object({
startDate: z.date(),
endDate: z.date(),
});
const schemaBothUndefined = z.object({
startDate: z.undefined(),
endDate: z.undefined(),
});
const bothOrNeither = schema.or(schemaBothUndefined);
console.log(bothOrNeither.safeParse({})); // success
console.log(bothOrNeither.safeParse({
startDate: new Date(),
endDate: new Date(),
})); // success
console.log(bothOrNeither.safeParse({
startDate: new Date(),
})); // failure
If the schema is to be used as part of a larger schema you can use and
for those fields like:
import { z } from "zod";
const startAndEnd = z.object({
CampaignStartDate: z.date(),
CampaignEndDate: z.date(),
});
const neitherStartNorEnd = z.object({
CampaignStartDate: z.undefined(),
CampaignEndDate: z.undefined(),
});
const CampaignDates = startAndEnd.or(neitherStartNorEnd);
export const MediumSchema = z.object({
id: z.string(),
}).and(CampaignDates);
console.log(MediumSchema.safeParse({ id: '11' })); // success
console.log(MediumSchema.safeParse({
id: '11',
CampaignStartDate: new Date(),
CampaignEndDate: new Date()
})); // Success
console.log(MediumSchema.safeParse({
id: '11',
CampaignEndDate: new Date()
})); // Failure
Upvotes: 5