T
TanStack13h ago
like-gold

How to make the default value of a field nullable?

I use Zod validation. I have an enum of programming languages, and have a field for choosing them. I want nothing to be in that field by default. TypeScript errors out because of the default value being set to undefined or null which don't pass as a string for the enum. Also, I can't set the value back to null or undefined or something similar from the field context. I don't really want to use empty strings.
No description
20 Replies
other-emerald
other-emerald13h ago
your schema seems to be incorrect though. does
language: z.enum(languageIds).nullable().optional()
language: z.enum(languageIds).nullable().optional()
make more sense?
like-gold
like-goldOP13h ago
I want the language field not to be able to be optional while submitting, tho I want the UI to be able to remove current value so when there's no value in the field, it fails validation
other-emerald
other-emerald13h ago
that's usually done with a superRefine also you might have to coerce your defaultValues to your schema type:
const defaultValues: z.input<typeof formSchema> = …
const defaultValues: z.input<typeof formSchema> = …
your initial value states that language can be undefined. so your superRefine then comes in and asserts that at submit time you must have a language
like-gold
like-goldOP13h ago
ok, gonna try that, thx for help! can refine work instead of superRefine?
other-emerald
other-emerald13h ago
refine works at the field level. your description seems to indicate you want it at a form level on submit so a superRefine is probably the right answer
like-gold
like-goldOP13h ago
I only originally wanted the validation to work on language, but still thanks for other help
other-emerald
other-emerald13h ago
lmk how it goes! also throwing in a plug for onDynamic in combination with revalidationLogic(). great UX
like-gold
like-goldOP13h ago
gonna check that out, thanks refine worked really well, everything works as I wanted it to onDynamic is also really cool, integrated that, thanks for telling me!
other-emerald
other-emerald12h ago
complete tangent, one pattern that worked for me recently was a z.union(v => isEmpty(v) ? null : v, z.string().email)) and all my validations went into the second argument in case it helps. happy coding!
like-gold
like-goldOP4h ago
thanks a lot!
stormy-gold
stormy-gold4h ago
for context, we do have some discussion about making defaultValues behave differently compared to validation (like nullable vs non-nullable), but I haven‘t heard from the user saying they‘ll make a PR the main purpose of the typecheck is to avoid locking down your form with wrongly assigned field errors
like-gold
like-goldOP4h ago
yeah, that would be logical
like-gold
like-goldOP4h ago
I think the code you provided doesn't really work though, I've changed it like this, but the union doesn't accept functions and even when I put it into an array it didn't work. I also don't really get how does the part with isEmpty work
No description
like-gold
like-goldOP4h ago
gonna keep it the previous option for now
like-gold
like-goldOP3h ago
the onSubmit typing doesn't change with the current approach, should I just non-null assertion?
No description
stormy-gold
stormy-gold3h ago
onSubmit doesn‘t receive outputs from schemas (since there can be multiple with competing transforms) however, a .parse works since it‘s guaranteed to pass the schema there‘s a section about this in the submission handling docs
like-gold
like-goldOP3h ago
ohh, sorry for not seeing that earlier, thanks for telling me about that!
stormy-gold
stormy-gold3h ago
for primitives, it‘d be straightforward. However, when you get into objects, it is a bit trickier. Should the object also allow null? Its properties probably should, but it could be another object etc etc
like-gold
like-goldOP3h ago
that should probably be configurable, but that would be hard to implement with TypeScript integrated similar code, really helped!
stormy-gold
stormy-gold3h ago
glad to hear!

Did you find this page helpful?