zod icon indicating copy to clipboard operation
zod copied to clipboard

Discriminated union doesn't work with `transform`

Open lobotomoe opened this issue 2 years ago • 4 comments

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

lobotomoe avatar May 27 '22 04:05 lobotomoe

Same issue here, love this operator, but I need to rename keys before the discriminatedUnion

oliverbutler avatar Jun 20 '22 13:06 oliverbutler

Does anyone know any workaround? This makes adding certain optional types based on other fields impossible, forcing you to always provide those

danielo515 avatar Jul 05 '22 11:07 danielo515

I made a pull request to address this issue as I have the same problem.

Waiting for merge or feedback

roblabat avatar Jul 26 '22 15:07 roblabat

I'm hitting this too, would love to see @roblabat's PR make it through

dagda1 avatar Aug 17 '22 09:08 dagda1

I'm also hitting this.

jeremyisatrecharm avatar Oct 06 '22 01:10 jeremyisatrecharm

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?

davidtorosyan avatar Dec 12 '22 02:12 davidtorosyan

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)

guilhermedelyra avatar Mar 14 '23 14:03 guilhermedelyra