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.