react-hook-form / resolvers

📋 Validation resolvers: Yup, Zod, Superstruct, Joi, Vest, Class Validator, io-ts, Nope, computed-types, typanion, Ajv, TypeBox, ArkType, Valibot, effect-ts and VineJS
https://react-hook-form.com/
MIT License
1.71k stars 155 forks source link

Not Possible to use Zod omit on schema passed to resolver #650

Open blacksandsolutions opened 8 months ago

blacksandsolutions commented 8 months ago

Describe the bug

When omit is used to modify a schema, that schema causes an error when passed to zod resolver.

To Reproduce I have a base schema for an Account.

export const AccountSchema = z.object({
    uid: z.string().uuid(),
    name: z
        .string({
            invalid_type_error: 'Please enter an account name.',
        })
        .pipe(nonempty),
    type: z.enum(['manual', 'auto'], {
        invalid_type_error: 'Please select a valid account type.',
    }),
})

For create form I extend this schema, omitting the uid

export const CreateAccountSchema = AccountSchema.omit({
    uid: true,
})

When the latter schema is passed to the resolver

Screenshot 2023-12-04 at 8 14 14 PM

I see this error when I try to submit / trigger form etc

Screenshot 2023-12-05 at 8 10 50 PM

If instead I pass AccountSchema like this, there is no error Screenshot 2023-12-04 at 8 16 28 PM

I'm not able to create code sandbox using this template - it opens in a beta version and there are no files / edit controls..?

Expected behavior Expect the Schema with omit applied to work the same as the original schema - e.g. not throw an error

blacksandsolutions commented 8 months ago

I've worked around this by spitting my schema up into two parts.

export const BaseAccountSchema = z.object({
    uid: z.string().uuid(),
})

export const CreateAccountSchema = x.object({
    name: z
        .string({
            invalid_type_error: 'Please enter an account name.',
        })
        .pipe(nonempty),
    type: z.enum(['manual', 'auto'], {
        invalid_type_error: 'Please select a valid account type.',
    }),
})

export const AccountSchema = BaseAccountSchema.merge(CreateAccountSchema)

This way I can use the CreateAccountSchema in the form and AccountSchema wherever I need to validate the full object

jbergeron03 commented 1 month ago

I encountered this issue too, and my solution was quite similar to yours.

Here’s an example with the same context:

export const AccountSchema = z.object({
    uid: z.string().uuid(),
    name: z
        .string({
            invalid_type_error: 'Please enter an account name.',
        })
        .pipe(nonempty),
    type: z.enum(['manual', 'auto'], {
        invalid_type_error: 'Please select a valid account type.',
    }),
})

And then put the attribute to undefined...

export const AccountSchema = BaseAccountSchema.merge(z.object({ uid: z.undefined() }));

This workaround isn't perfect, but it was the best solution for my context. I wish omit worked out of the box.