zod
zod copied to clipboard
Discriminated union doesn't work with `transform`
Possibly it is not bug. Any way to "post"-define discriminator (define in transform
)?
Codesandbox example 1 Codesandbox example 2
Example 1:
import z from "zod";
const schemaA = z
.object({
mo: z.number().optional(),
aa: z.number()
})
.transform((content) => ({
...content,
k: "kindA" as const
}));
const schemaB = z
.object({
mi: z.number().optional(),
aao: z.number()
})
.transform((content) => ({
...content,
k: "kindB" as const
}));
const schemaC = z.discriminatedUnion("k", [schemaA, schemaB]);
Example 2:
import z from "zod";
const schemaA = z.object({
T: z.literal("error"),
c: z.number(),
m: z.string()
});
const schemaB = z
.object({
T: z.literal("ss"),
mi: z.number().optional(),
aao: z.number()
})
.transform((content) => ({
...content,
someField: "someValue" as const
}));
const schemaC = z.discriminatedUnion("T", [schemaA, schemaB]);
Error: The discriminator value could not be extracted from all the provided schemas
Same issue here, love this operator, but I need to rename keys before the discriminatedUnion
Does anyone know any workaround? This makes adding certain optional types based on other fields impossible, forcing you to always provide those
I made a pull request to address this issue as I have the same problem.
Waiting for merge or feedback
I'm hitting this too, would love to see @roblabat's PR make it through
I'm also hitting this.
I see the fix is now available in v3.20.0-beta, but when I upgraded and tried the first example I got this error:
Type 'ZodEffects<ZodObject<{ mo: ZodOptional<ZodNumber>; aa: ZodNumber; }, "strip", ZodTypeAny, { mo?: number | undefined; aa: number; }, { mo?: number | undefined; aa: number; }>, { ...; }, { ...; }>' is missing the following properties from type 'ZodObject<{ k: ZodTypeAny; } & ZodRawShape, any, any, { [x: string]: any; }, { [x: string]: any; }>': _cached, _getCached, shape, strict, and 14 more.ts(2740)
Am I doing something wrong?
I see the fix is now available in v3.20.0-beta, but when I upgraded and tried the first example I got this error:
Type 'ZodEffects<ZodObject<{ mo: ZodOptional<ZodNumber>; aa: ZodNumber; }, "strip", ZodTypeAny, { mo?: number | undefined; aa: number; }, { mo?: number | undefined; aa: number; }>, { ...; }, { ...; }>' is missing the following properties from type 'ZodObject<{ k: ZodTypeAny; } & ZodRawShape, any, any, { [x: string]: any; }, { [x: string]: any; }>': _cached, _getCached, shape, strict, and 14 more.ts(2740)
Am I doing something wrong?
same here, using the newest version (3.21.4)
export const BaseRegistryTag = z
.object({
id: z.optional(z.string()),
name: z.string(),
description: z.optional(z.string()),
})
.strict();
const positiveNumber = z.number().positive().finite()
const hasLengthType = z.object({
minLength: positiveNumber,
maxLength: positiveNumber
}).refine((data) => data.maxLength >= data.minLength, "maxLength should be greater than or equal to minLength.")
export const NumberTag = BaseRegistryTag.extend({
type: z.literal('number'),
precision: z.optional(positiveNumber),
}).and(hasLengthType)
export const TextTag = BaseRegistryTag.extend({
type: z.literal('text'),
}).and(hasLengthType)
export const RegistryTag = z.discriminatedUnion('type', [NumberTag, TextTag])
gives:
Type 'ZodIntersection<ZodObject<{ id: ZodOptional<ZodString>; name: ZodString; description: ZodOptional<ZodString>; type: ZodLiteral<"number">; precision: ZodOptional<...>; }, "strict", ZodTypeAny, { ...; }, { ...; }>, ZodEffects<...>>' is missing the following properties from type 'ZodObject<{ type: ZodTypeAny; } & ZodRawShape, UnknownKeysParam, ZodTypeAny, { [x: string]: any; type?: any; }, { [x: string]: any; type?: any; }>': _cached, _getCached, shape, strict, and 14 more.ts(2740)