Best practice typing a boolean field using zod (or other schema library)
Let's say I have a field in my form where a user has to pick "yes" or "no". There is no default.
Arguably I would use a zod type like so
isDogOwner: z.boolean()
Now, if I don't provide a default value in my defaultValues, typescript will complain that it's not matching the schema.
If I make it optional in zod, it will be optional in defaultValues.. but now my form validation is not right since I need the user to make a choice before submitting.
In text fields this is not a problem since you just use an empty string, but what do we do in these scenarios? I feel like something in the typescript implementation is wrong here, my gut is telling me that defaultValues should be a Partial of the schema so you can chose if you shall provide a default or not for a specific field. Thoughts, suggestions?12 Replies
correct-apricotβ’5mo ago
tanstack form works with the input type of zod schemas. That means you can achieve the effect you want using
transform
, refine
or superRefine
z.boolean().nullable().refine(v => v !== null, 'Please select an option!')
That will turn the output type into a boolean, but allow null as an input type.
in onSubmit
, you will have to parse value
once more to receive the output value, as you'll receive the input typeharsh-harlequinOPβ’5mo ago
Thanks for the quick feedback! that make sense. No zod expert here, will try it out π
eastern-cyanβ’5mo ago
β¬οΈ this
Also, Valibot has a picklist (https://valibot.dev/api/picklist/) that might be another approach to this problem.
isDogOwner: v.picklist(["yes", "no"])
Maybe this turns into something like this at some pointβ¦
isDogOwner: v.picklist(["no", "1 dog", "2 dogs"])
or even
hasPets: v.picklist(["no", "1 dog", "2 dogs", "1 cat", "2 cats"])
That's what I've seen for rental properties (you get the option to take 1 or two dogs/cats max)harsh-harlequinOPβ’5mo ago
I tried this little snippet, but I still got some type errors. On the onBlur field I got
The types of 'input.isDogOwner' are incompatible between these types.
Type 'boolean | null' is not assignable to type 'null'.
Type 'false' is not assignable to type 'null'.ts(2322)
I'm on zod 3.24.3 and tanstack 1.6.3
correct-apricotβ’5mo ago
what's likely happening is that
* it infers that
isDogOwner
is boolean
since you passed false
to it
* sees that the schema is nullable
try extracting the defaultValues so that it knows it's related to the schema:
harsh-harlequinOPβ’5mo ago
Yepp that did work π Would be nice if you wouldn't have to be explicit about it though
correct-apricotβ’5mo ago
well, that's a limitation of typescript. it implicitly creates a separate type since you didn't hint at the schema and defaultValues being related at all
harsh-harlequinOPβ’5mo ago
Yeah, I guess it depends on if the type is defined by the defaultValues field or by the schema no? Now it's more that you need to pass in a schema that matches the type defined by your defaultValues field.
correct-apricotβ’5mo ago
typescript has functionality to control the flow of assignment (NoInfer, Infer), but this is a case of conflict between two infers
so you could tell typescript to never use defaultValues as reference, but people tend to do
telling it to not use schemas as reference would break the code you provided
and the current situation has conflicts as you saw
harsh-harlequinOPβ’5mo ago
telling it to not use schemas as reference would break the code you providedWhat do you mean by this? My code was already broken π But If useAppForm would use input type from the zod schema It would work since it's a wider type. But if this would be better or not I'm not sure, but it's what i expected in this case
correct-apricotβ’5mo ago
yeah, that's what I meant. It wouldn't solve the situation. And if it worked in your favor, it would break every person that didn't pass schemas
at least that's how I understood the current typing. I'm not too well versed in typescript to know if a solution would exist
harsh-harlequinOPβ’5mo ago
mmm same here.. I would assume that you could fallback to the type of defaultValues if a schema was not provided
But thanks! I would consider my problem solved π