zod icon indicating copy to clipboard operation
zod copied to clipboard

Cannot use branding and flavoring with Lazy

Open luixo opened this issue 3 years ago • 10 comments

Hello, I'm using flavoring concept while working with zod, and I stumbled upon typing the recursive pattern. That is the case:

import {z} from 'zod';

type Flavored<
  T extends string,
> = string & {
  __flavor: T;
};

const flavored = <T extends string>(x: string): x is Flavored<T> => true;

const flavoredType = z.string().refine<Flavored<'flavor1'>>(flavored);

const fooSchema = z.strictObject({
  kind: z.literal('foo'),
  data: flavoredType,
});

type ComplexSchema =
  | z.infer<typeof fooSchema>
  | {
      kind: 'complex';
      schemas: ComplexSchema[];
    };

const complexSchema: z.ZodType<ComplexSchema> = z.lazy(() =>
  z.union([
    fooSchema,
    z.strictObject({
      kind: z.literal('complex'),
      schemas: z.array(complexSchema),
    }),
  ]),
);

It ends up with an error:

Type 'ZodLazy<ZodUnion<[ZodObject<{ kind: ZodLiteral<"foo">; data: ZodEffects<ZodString, Flavored<"flavor1">, string>; }, "strict", ZodTypeAny, { ...; }, { ...; }>, ZodObject<...>]>>' is not assignable to type 'ZodType<ComplexSchema, ZodTypeDef, ComplexSchema>'.
  Types of property '_input' are incompatible.
    Type '{ kind: "foo"; data: string; } | { kind: "complex"; schemas: ComplexSchema[]; }' is not assignable to type 'ComplexSchema'.
      Type '{ kind: "foo"; data: string; }' is not assignable to type 'ComplexSchema'.
        Type '{ kind: "foo"; data: string; }' is not assignable to type '{ kind: "foo"; data: Flavored<"flavor1">; }'.
          Types of property 'data' are incompatible.
            Type 'string' is not assignable to type 'Flavored<"flavor1">'.
              Type 'string' is not assignable to type '{ __flavor: "flavor1"; }'.

It seems like data loses its refinement in this case. If I change data to be z.string() everything works perfectly.

luixo avatar Oct 17 '22 13:10 luixo

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jan 15 '23 14:01 stale[bot]

Nope, that is still needed.

luixo avatar Jan 15 '23 22:01 luixo

This also seems to happen when combining recursive schemas and branded types.

const baseThingSchema = z.object({
  id: z.string().brand<"thing">(),
  otherField: z.string(),
});

type Thing = z.infer<typeof baseThingSchema> & {
  subThings: Thing[];
};

const thingSchema: z.ZodType<Thing> = baseThingSchema.extend({
  subThings: z.lazy(() => z.array(thingSchema)),
});

This :point_up: results in the following error:

Type 'ZodObject<{ id: ZodBranded<ZodString, "thing">; otherField: ZodString; subThings: ZodLazy<ZodArray<ZodType<Thing, ZodTypeDef, Thing>, "many">>; }, "strip", ZodTypeAny, { ...; }, { ...; }>' is not assignable to type 'ZodType<Thing, ZodTypeDef, Thing>'.
  Types of property '_input' are incompatible.
    Type '{ id: string; otherField: string; subThings: Thing[]; }' is not assignable to type 'Thing'.
      Type '{ id: string; otherField: string; subThings: Thing[]; }' is not assignable to type '{ id: string & BRAND<"thing">; otherField: string; }'.
        Types of property 'id' are incompatible.
          Type 'string' is not assignable to type 'string & BRAND<"thing">'.
            Type 'string' is not assignable to type 'BRAND<"thing">'.

50 const thingSchema: z.ZodType<Thing> = baseThingSchema.extend({

Switching the branded type to a string causes the error to go away

eriktate avatar Mar 12 '23 13:03 eriktate

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jun 12 '23 10:06 stale[bot]

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Sep 10 '23 15:09 stale[bot]

Still not resolved

luixo avatar Sep 10 '23 18:09 luixo

I have the same error. Please fix it.

mitsuru793 avatar Sep 22 '23 23:09 mitsuru793

@scotttrinh Can I help somehow to get this addressed?

luixo avatar Mar 02 '24 23:03 luixo