Conditional zod schema on onSubmit form validator
Probably a skill issue but Is it possible to handle 2 zod schemas conditionally ?
export const createEmployeeSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
firstName: z.string().min(2),
});
export const updateEmployeeSchema = createEmployeeSchema.omit({
password: true
});
and on the form do something like this
Since not much changes besides the password field (which is removed in update form), I'd rather share the same form component
But then on my password form.Field I get this typescript error when trying to render the errors for that field because the error object is unknown

21 Replies
xenial-blackOP•2mo ago
This is the form component

xenial-blackOP•2mo ago
I guess I can call it a type issue
exotic-emerald•2mo ago
I think I'd use a https://zod.dev/api?id=discriminated-unions#discriminated-unions here and put the info if it is a "create" or and "update" into the Schema.
You should be able to remove some conditions then as well (the once in
validators.onSubmit
, onSubmit
at least)
To take it further you could use .transform()
to transform the values the user inputs into the form to what your API needs.
xenial-blackOP•2mo ago
Discriminated Union is a nice suggestion, I was able to get rid of the error on the form Field level,
here's my current code for the useForm, I am wondering why doesn't the value inside if infer the type based on the values.type, am I missing something ?

fair-rose•2mo ago
because typescript assumes it‘s just some object instead of a zod schema input
try extracting defaultValues and type it as z.input<>
xenial-blackOP•2mo ago
Yeah, it takes the object as whole {} | {}
fair-rose•2mo ago
and likely the type property as string instead of literal
xenial-blackOP•2mo ago
Yeah typing default values with z.infer does the job
fair-rose•2mo ago
input != infer == output
works for this schema, but keep it in mind for schemas that have transforms
exotic-emerald•2mo ago
defaultValues
= z.input
and I'd say it's good practive to v.parse
before passing data to the mutation - this way if you change the Schema and you're adding transformations it "just works" 🪄xenial-blackOP•2mo ago
@ksgn is this good ?, I could probably just pass one object with conditional field like u just mentioned, but overall looks great

exotic-emerald•2mo ago
I think you can just
upsertEmployeeSchema.parse
in onSubmit
- the Schema knows what to do depending on the type
@Luca | LeCarbonator should the Schema on the right side not be exhaustive? (Lines 19-22)
So: Instead of omit
just relax the rules z.any
or z.string
xenial-blackOP•2mo ago
By relaxing you mean just duplicate whatever is on createEmployeeSchema and make the password/role z.any?
fair-rose•2mo ago
when it comes to the output, it will remove any extra. If I understood it correctly, it won‘t error for having any extra unless you add
.strict()
exotic-emerald•2mo ago
that's what I do, but I'm using valibot. I'm also transforming my schemas to what the Backend wants and parsing (as I suggested before).
That pattern works pretty nicely
You'll end up with a Schema that you can throw data against, it'll take it and transform it to the expected output or it'll provide you with an error message
xenial-blackOP•2mo ago
Okay that's interesting, I would like to see that approach, I made a codesandbox to play with it, https://codesandbox.io/p/devbox/gifted-tristan-yjy584
Im kinda confused though, im typing the defaultValues as upsertingEmployeeSchema which is a discriminatedUnion, Im also conditionally parsing the schema but when I hover over parsedValue inside value.type === 'create' it still shows both types,
fair-rose•2mo ago
that‘s because upsert accepts both create and update, which means the parsed output may be both create and update
so the condition check before passing it in should be unnecessary
exotic-emerald•2mo ago
inside the
if
parsedValue is now:
use the parsedValue
- once you've put the value
you get from onSubmit
through zods parse
you probably do not want to use it anymorexenial-blackOP•2mo ago
Oh, I was checking against the value from submit, got it, thanks a lot guys for the feedback
xenial-blackOP•2mo ago
@ksgn Ill stick to this version, LGTM

xenial-blackOP•2mo ago
It feels better to omit password and role from the schema IMO