Max
Max

Reputation: 679

Require none or both fields with Zod

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

Answers (1)

Souperman
Souperman

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

Edit: Further details when part of a larger schema

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

Related Questions