Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schema in object being inferred differently (and weirdly) #2654

Open
ericallam opened this issue Aug 14, 2023 · 13 comments · May be fixed by #4030
Open

Schema in object being inferred differently (and weirdly) #2654

ericallam opened this issue Aug 14, 2023 · 13 comments · May be fixed by #4030

Comments

@ericallam
Copy link

See the following TS snippet:

import { z } from "zod";

const EventNameSchema = z.string().or(z.array(z.string()));

type EventName = z.infer<typeof EventNameSchema>;
// EventName is string | string[]

const EventSchema = z.object({
  name: z.string().or(z.array(z.string())) // this is the same as the EventNameSchema
});

type EventWithName = z.infer<typeof EventSchema>;
type EventName2 = EventWithName["name"];
// EventName2 is (string | string[]) & (string | string[] | undefined)

And the TS playground: link

I'm not sure if this is intended or a bug or maybe just a user error. Using zod 3.21.4 and TS 4.8.4

@algora-pbc
Copy link

💎 $25 bounty created by @ericallam
👉 To claim this bounty, submit your pull request on Algora
📝 Before proceeding, please make sure you can receive payouts in your country
💵 Payment arrives in your account 2-5 days after the bounty is rewarded
💯 You keep 100% of the bounty award
🙏 Thank you for contributing to colinhacks/zod!

@kremedev
Copy link

Add "strictNullChecks": false to tsconfig.json

fvckDesa added a commit to fvckDesa/zod that referenced this issue Aug 23, 2023
fvckDesa added a commit to fvckDesa/zod that referenced this issue Aug 23, 2023
fvckDesa added a commit to fvckDesa/zod that referenced this issue Aug 24, 2023
@zcesur
Copy link

zcesur commented Aug 24, 2023

had a similar issue recently, seems to be due to the split & intersect approach for inferring object types

typing addQuestionMarks more precisely does resolve this issue:

 export type addQuestionMarks<
   T extends object,
   R extends keyof T = requiredKeys<T>
- > = Pick<Required<T>, R> & Partial<T>;
+ > = Pick<Required<T>, R> & Omit<Partial<T>, R>;

but also introduces new problems like breaking the inference of generic schemas (as the compiler can no longer determine their shape)

relevant thread by @colinhacks

@szulcus
Copy link

szulcus commented Aug 28, 2023

I have the same problem:

Works fine:

const test = string().array().or(record(string()));
type Test = z.infer<typeof test> // string[] | Record<string, string>

Don't work:

const test = object({ values: string().array().or(record(string())) });
type Test = z.infer<typeof test>; // { values: (string[] | Record<string, string>) & (string[] | Record<string, string> | undefined); }

@VirtualDharm
Copy link

#2654

@omermizr
Copy link

omermizr commented Nov 8, 2023

Honestly this makes zod unusable for me (using strict TS). Guess I'll stick with v3.21.1 and copy over the email validation schema from v3.22.3 for now

@MadhavPujara
Copy link

@ericallam has this issue been resolved if not can you assign it to me

@AlexGalays
Copy link

AlexGalays commented Jan 4, 2024

It's still here in 3.22.4

In particular, our use case is:

const role = z.enum(["Administrator", "Writer", "Readonly"])
const rolesPerLocale = z.record(role.optional())
const repositoryRole = role.or(rolesPerLocale)

// Then later
    z.object({
      role: repositoryRole
    })

This makes us unable to later use typeof role === "string" to discriminate between the basic role and the rolePerLocale because we get this weird, impossible string & {} in the signature.

@abhi12299
Copy link

@AlexGalays with the PR #3138 I believe this will get sorted out. This is what I get from running the code you provided. This seems to be the right type inference.

image

@Harshit0741
Copy link

/attempt #2654

@FayadIdriss
Copy link

I can work on this ticket I can be assigned @ericallam

@Kunal-Darekar Kunal-Darekar linked a pull request Mar 16, 2025 that will close this issue
@Kunal-Darekar
Copy link

/attempt #4030

@sparkybug
Copy link

Hi @ericallam , is this still open to work on?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet