Is it possible to convert string formatted numbers to numbers before using a value in z.discriminatedUnion? Here is an example code snippet:
import { z } from "zod";
const BrushColorEnum = z.enum(
["BLUE_SILVER", "GREEN_SILVER", "RED", "GREEN_BLACK"],
{ message: "Invalid option" }
);
const BrushTypeEnum = z.enum(["THREAD", "MIXED", "CARLITE"], {
message: "Invalid option",
});
const noBrushSchema = z.object({
brush_qty: z.preprocess(
(val) => (typeof val === "string" ? parseInt(val, 10) : val),
z.literal(0)
),
brush_type: z
.union([
z.string().length(0, { message: "Invalid option" }),
z.undefined(),
z.literal(false),
])
.transform(() => undefined),
brush_color: z
.union([
z.string().length(0, { message: "Invalid option" }),
z.undefined(),
z.literal(false),
])
.transform(() => undefined),
});
const brushSchema = z.discriminatedUnion("brush_qty", [
noBrushSchema,
z.object({
brush_qty: z.literal("2"),
brush_type: BrushTypeEnum,
brush_color: BrushColorEnum,
}),
z.object({
brush_qty: z.literal("3"),
brush_type: BrushTypeEnum,
brush_color: BrushColorEnum,
}),
]);
console.log(brushSchema.safeParse({ brush_qty: "0" }).error); // message: "Invalid discriminator value. Expected 0 | '2' | '3'"
console.log(brushSchema.safeParse({ brush_qty: 0 })); // success
Regarding the brush_qty
field, while I expected it to convert the string to a number and accept the second safeParse
, it appears that the validation occurs before reaching the schema section.
In cases where converting to number
is not feasible, what other options do I have besides discriminatedUnion
to achieve similar functionality?
Thank you in advance!