Cannot use branding and flavoring with Lazy
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.
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.
Nope, that is still needed.
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
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.
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.
Still not resolved
I have the same error. Please fix it.
@scotttrinh Can I help somehow to get this addressed?