typescript - Kräver inga eller båda fälten med Zod


Jag har egenskaperna startDate och endDate i ett Zod-schema. Jag skulle vilja verifiera att antingen:

  • Ingen av dem är inställd
  • Båda är inställda

Det vill säga, om bara startDate eller bara endDate är inställt, kommer analysen att misslyckas.

Schemat ser ut så här:

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))
});

Hur uppnår jag detta?

Svar #1

Du kan använda union eller den inbyggda or-metoden för att förena de två möjliga scheman du förväntar dig. Till exempel:

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

Redigera: Ytterligare detaljer när det är en del av ett större schema

Om schemat ska användas som en del av ett större schema kan du använda and för de fälten som:

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

Relaterade artiklar