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

Intersection of object and record fails if function is used as a value for both #3485

Open
callumgare opened this issue May 11, 2024 · 0 comments

Comments

@callumgare
Copy link

I want to replicate the following type in zod:

{
  foobar: () => {},
  [key: string]: () => {} | string
}

I believe something like the following should do it:

z.object({
  foobar: z.function(),
}).and(
  z.record( z.union([ z.function(), z.string() ]) )
)

And indeed that pattern does work fine if you replaced z.function() with something like z.number():

const schema = z.object({
  foobar: z.number(),
}).and(
  z.record( z.union([ z.number(), z.string() ]) )
)

// Succeeds!
schema.parse({ foobar: 100, test: 42 })

But unfortunately this does not work with z.function():

const schema = z.object({
 foobar: z.function(),
}).and(
 z.record( z.union([ z.function(), z.string() ]) )
)

// Fails with error "invalid_intersection_types: Intersection results could not be merged" :(
schema.parse({ foobar: () => {}, test: () => {} })

My understanding/best guess of why it's failing:
When ZodIntersection is passed it calls the mergeValues function which determines that foobar is a key shared in both a and b. Because of this it will then recursively call mergeValues on the values of the foobar property from both a and b. In the case above where z.number() is used this will succeed because the number 100 from both a and b will === each other and thus the merge will be marked as valid. But in the case of z.function() both a.foobar and b.foobar are considered different objects (since it looks like zod creates a different object wrapped around the original () => {} object or something like that, I'm not really sure) and thus they are not consided equal and will fail.

Thanks for reading and for such an extremely useful library!

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

No branches or pull requests

1 participant