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

How to union or merge two or more z.record schemas #3745

Open
asuthr-zesty opened this issue Sep 6, 2024 · 1 comment
Open

How to union or merge two or more z.record schemas #3745

asuthr-zesty opened this issue Sep 6, 2024 · 1 comment

Comments

@asuthr-zesty
Copy link

Thanks for the great library, really finding it useful.

Is there a recommended way to define a union of two or more record schemas, that would successfully parse an object with a mix of key/values from each record? Here's a minimal example outlining my unsuccessful attempt:

import { z } from 'zod';

// Define the schemas for the individual records
const record1Schema = z.record(z.enum(['a', 'b']), z.union([z.number(), z.string()]));

const record2Schema = z.record(z.enum(['c', 'd']), z.union([z.boolean(), z.string()]));

// Define the merged schema
const mergedSchema = z.union([record1Schema, record2Schema]);

// Example usage
const example1 = { a: 42, b: 'hello' }; // Valid according to record1Schema
const example2 = { c: true, d: 'world' }; // Valid according to record2Schema
const example3 = { a: 42, c: true }; // Valid according to mergedSchema

console.log(record1Schema.safeParse(example1)); // Success
console.log(record2Schema.safeParse(example2)); // Success
console.log(mergedSchema.safeParse(example3)); // Error

The last parse fails with invalid_union errors that includes invalid_enun_values errors like this:

{                                                                                                                
              "received": "c",               
              "code": "invalid_enum_value",      
              "options": [                                                                                                   
                "a",            
                "b"                                                                                                          
              ],                                                                                                             
              "path": [                                                                                                      
                "c"                                                                                                          
              ],                                                                                                             
              "message": "Invalid enum value. Expected 'a' | 'b', received 'c'"                   
            }

I would expect it to work (and it does type check), but it seems like it expects it to conform to one of the record schemas only, and won't accept the other. Is there a better way to do this?

@sunnylost
Copy link

I suggest using superRefine() to gain more custom control.

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

2 participants