antonwilhelm
antonwilhelm

Reputation: 7573

How to make Object Properties flexible with Zod?

New to Typescript, Zod & Trpc.

Say I have a schema for both animals & plants. I want to store all their common properties in the "root" of the schema and then put the more specific properties into a sub-object called custom. (just a made-up example to simplify things)

So far I have this:

create: t.procedure
    .input(z.object({
      id: z.string(),
      type: z.string(), //can be "ANIMAL" or "PLANT"
      //all other common properties go here
      //...
      custom: z.object({ fur: z.string() }) //...if it's an animal, it will have "fur" here, if it's a plant something entirely different, like "seeds"
    }).nullish())

I don't understand how to get this to work, or how I would accomplish this with zod. I looked into zods discriminated union, but I don't seem to fully understand how the syntax works?

Upvotes: 2

Views: 6403

Answers (1)

Souperman
Souperman

Reputation: 10006

This is a good example of when you would use discriminatedUnion.

For example:

const inputSchema = z.discriminatedUnion("type", [
  z.object({
    id: z.string(),
    type: z.literal('ANIMAL'),
    custom: z.object({ fur: z.string() }),
  }),
  z.object({
    id: z.string(),
    type: z.literal('PLANT'),
    custom: z.object({ seeds: z.number() }),
  })
]).nullish();

You could then pass that schema into input(). If you have a lot of shared fields, you could store those in a base schema which you would merge in once rather than duplicating them in each branch.

Upvotes: 1

Related Questions