Open gorinovsoft opened 1 week ago
You can switch firstUser
and secondUser
position in union.
const UserSchema = z.union([secondUser, firstUser]);
Zod will iterate through all the options in a union array. If any of the options pass validation, the entire result is considered valid. However, if any of the options fail validation, it will return the result of the first invalid option and ignore the rest.
For example, if you use z.union([firstUser, secondUser])
to parse { firstName: "", lastName: "", testProperty: "" }
, the firstUser
schema will raise 3 errors, so that becomes the result. Even if you try parsing { firstName: "", lastName: "", testProperty: "", testPropertySecond: "" }
, the outcome remains the same. This happens because firstUser
is the first option evaluated, and Zod will return its result, ignoring the secondUser
schema.
@sunnylost it could be a working solution, but if we change the order of zod schemas in the array and then decide to add a property with the same key but with different validation schema, validation will raise error in the testPropertySecond
property. Take a look at this example below:
So the issue is that you want to use the firstUser
schema to parse the first user and the secondUser
schema for the second, but since both users have the same structure, there's no way to determine which schema to apply. In my opinion, each user should have a property to distinguish them, allowing you to use a discriminated union for validation.
So the issue is that you want to use the
firstUser
schema to parse the first user and thesecondUser
schema for the second, but since both users have the same structure, there's no way to determine which schema to apply. In my opinion, each user should have a property to distinguish them, allowing you to use a discriminated union for validation.
Yes, you are right! We want to apply the schema to object depends on some key (for example, id from enum). Unfortunately, zod union do not support the determination of validation schema according to key property and its value. We have z.discriminatedUnion
which could help if it could work with transformed zod schemas.
Currently, there is an issue in the schema where, if identical fields are present in the user's schemas, Zod incorrectly validates the second testProperty field. Is there a way to fix this? At the moment, the only solution I've found is to change the field name (testProperty) to a unique one.
https://codesandbox.io/p/sandbox/zodschemas-forked-76tlcr?file=%2Fsrc%2FApp.tsx
`import { useCallback, VFC } from "react"; import { SubmitHandler, useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod";
const stringSchema = z.string().min(1, { message: "fieldIsRequired" });
const firstUser = z.object({ firstName: stringSchema, lastName: stringSchema, testProperty: stringSchema, });
const secondUser = z.object({ firstName: stringSchema, lastName: stringSchema, testProperty: stringSchema.or(z.string().length(0)), testPropertySecond: stringSchema.or(z.string().length(0)), });
const UserSchema = z.union([firstUser, secondUser]);
const usersSchema = z.object({ users: UserSchema.array(), });
type UsersForm = z.infer;
export const App: VFC = () => { const { register, handleSubmit, formState, control } = useForm({
resolver: zodResolver(usersSchema),
defaultValues: {
users: [
{
firstName: "",
lastName: "",
testProperty: "",
},
{
firstName: "",
lastName: "",
testProperty: "",
testPropertySecond: "",
},
],
},
});
const errors = formState.errors;
console.log(errors, formState, control);
const onSubmit: SubmitHandler = useCallback(async (value) => {},
[]);
return ( <form onSubmit={handleSubmit(onSubmit)} style={{ display: "flex", flexDirection: "column", width: 512, margin: "0 auto", }}
); }; `