How to use advanced Zod discriminate union?

302 Views Asked by At

I have a problem with my Zod schemas. I am creating a product that has common characteristics. However, it also has two dynamic data sets: simple and variables. These are defined by the "type" data. To achieve this, I am using a discriminated union.

// This schema is used if product.type === simple
const simpleSchema = z.object({
   simplename: z.optional(z.string()),
   stock: z.optional(z.number())
});

// This schema is used if product.type === variables
const variablesSchema = z.object({
   variablesname: z.optional(z.string()),
   stock: z.optional(z.number())
});

export const simpleProductFormValue = z.object({
// name, image, etc.
   isStockable: z.boolean().default(false),
   type: z.enum(["simple"]),
   simple: simpleSchema
});

export const variablesProductFormValue = z.object({
   // name, image, etc.
   isStockable: z.boolean().default(false),
   type: z.enum(["variables"]),
   variables: variablesSchema
});

const productFormValue = z.discriminatedUnion("type", [
   variablesProductFormValue,
   simpleProductFormValue
]);

So far, everything is okay. My choice of type returns the correct schema to validate.

My problem is at a higher level. As you can see in my base schema, there's a boolean called isStockable, and I want that if it is active, the stock fields (for simple or variables) should be required, and if it is inactive, I want them to be nullable.

What are the simplest solutions to achieve this? Of course, it would be possible to create each schema for simple and variable in a discriminated union (I think, at least), but the problem is that when I add new types of products, I will have to recreate schemas exponentially.

0

There are 0 best solutions below