colinhacks / zod

TypeScript-first schema validation with static type inference
https://zod.dev
MIT License
33.03k stars 1.15k forks source link

Inferred type imported from library has all fields as optional #3710

Open stefanlogue opened 1 month ago

stefanlogue commented 1 month ago

I've got a schema and inferred type in a library:

const schema = z.object({
  name: z.string(),
  address: z.string(),
});

type SchemaType = z.infer<typeof schema>;

I'm importing this inferred type into a project, and for some reason all of the fields are showing as potentially undefined. It's got an enum in there and it also shows undefined.

The type signature for the schema in the library looks like this:

const schema = z.ZodObject<{
  name: z.ZodString;
  addresss: z.ZodString;
}, "strip", z.ZodTypeAny, {
  name: string;
  address: string;
}, {
  ...;
}>

The type signature for the schema when imported into the project looks like this:

const schema = z.ZodObject<{
  name: z.ZodString;
  addresss: z.ZodString;
}, "strip", z.ZodTypeAny, {
  name?: string | undefined;
  address?: string | undefined;
}, {
  ...;
}>

I've got strict: true in both tsconfig.json files (the library and the project). strictNullChecks is not set in either.

Library: Zod 3.23.8 TS 5.4.5

Project: Zod 3.23.8 TS 4.9.5

Where am I going wrong?

colinhacks commented 1 month ago

You need "strictNullChecks": true in your tsconfig.json.

https://github.com/colinhacks/zod/issues/43

stefanlogue commented 1 month ago

The comments there say I just need to ensure that strictNullChecks isn't set to false, which it isn't.

Still, even with this set in the consuming project, they show as undefined.

Weirdly, this is only an issue when I import a type from a library. If I define the type inline and infer it, it behaves as expected.

If I import the schema and .strip() it, the inferred type works as expected.

trey-yeager-FHR commented 4 weeks ago

I believe I'm running into the same issue. When I import the inferred type across projects the type gets a [x: string]: any property added as well as all my fields are not optional and my fields that were using z.nativeEnum have become any.

For me importing the schema instead and then trying to infer the type within my consuming project didn't work like it did for Stefan.

Edit: I was able to find a fix thanks to this SO post: https://stackoverflow.com/questions/74185198/typescript-losing-zod-and-trpc-types-across-monorepo-projects-types-result-in

Basically need to set "compilerOptions": { "composite": true } within the tsconfig of the project that contains the Zod schema definitions and type inferences. Then in the project using it you need to set "references": [ { "path": "path/to/other/tsconfig" }].

stefanlogue commented 1 week ago

Still getting this issue, I've got "strictNullChecks": true, "strict": true in both of my tsconfig.json files. When I look at the inferred type in the library, it is correct. When I import that type into my project, everything is now optional. Using the schema to safeParse leaves everything optional. Does anyone have any idea on how to fix this?