Z
Zod4mo ago
Svish

Svish - Does inference somehow work differently...

Does inference somehow work differently with v4 than v3? https://discord.com/channels/893487829802418277/1374618927920971817
1 Reply
Svish
SvishOP4mo ago
I have something along the lines of this in v3, which has been working great, the r3 is correctly typed as { foo: string }:
import {
z as z3,
type ZodType as ZodType3,
type ZodTypeDef as ZodTypeDef3,
} from 'zod/v3';

interface FetchOptions3<ResponseData = unknown> {
meta?: { schema?: ZodType3<ResponseData, ZodTypeDef3, unknown> };
};

export async function fetch3<R>(
url: string,
{ meta }: FetchOptions3<R>
): Promise<R> {
await new Promise((resolve) => setTimeout(resolve, 300));
return {} as R;
}

const s3 = z3.object({ foo: z3.string() });

const r3 = await fetch3('https://example.com', {
meta: {
schema: s3,
},
});
import {
z as z3,
type ZodType as ZodType3,
type ZodTypeDef as ZodTypeDef3,
} from 'zod/v3';

interface FetchOptions3<ResponseData = unknown> {
meta?: { schema?: ZodType3<ResponseData, ZodTypeDef3, unknown> };
};

export async function fetch3<R>(
url: string,
{ meta }: FetchOptions3<R>
): Promise<R> {
await new Promise((resolve) => setTimeout(resolve, 300));
return {} as R;
}

const s3 = z3.object({ foo: z3.string() });

const r3 = await fetch3('https://example.com', {
meta: {
schema: s3,
},
});
But when I switch to v4, it breaks, and r4 here instead gets inferred as any:
import {
z as z4,
type ZodType as ZodType4
} from 'zod/v4';

interface FetchOptions4<ResponseData = unknown> {
meta?: { schema?: ZodType4<ResponseData> };
};

export async function fetch4<R>(
url: string,
{ meta }: FetchOptions4<R>
): Promise<R> {
await new Promise((resolve) => setTimeout(resolve, 300));
return {} as R;
}

const s4 = z4.object({ foo: z4.string() });

const r4 = await fetch4('https://example.com', {
meta: {
schema: s4,
},
});
import {
z as z4,
type ZodType as ZodType4
} from 'zod/v4';

interface FetchOptions4<ResponseData = unknown> {
meta?: { schema?: ZodType4<ResponseData> };
};

export async function fetch4<R>(
url: string,
{ meta }: FetchOptions4<R>
): Promise<R> {
await new Promise((resolve) => setTimeout(resolve, 300));
return {} as R;
}

const s4 = z4.object({ foo: z4.string() });

const r4 = await fetch4('https://example.com', {
meta: {
schema: s4,
},
});
The only difference here is the change to the ZodType type, which no longer requires the ZodTypeDef generic, and the schema itself being a v4 type instead of a v3 type. I can't figure out why any of this should break the inference and give me any. Anyone else ran into this?

Did you find this page helpful?