Complex object Select field, no reasonable defaultValue, and validation
I've got a "Create equipment" form. It's got 2 required selections, which will determine relations with other data. There's a "model" for selecting the equipment model relation, and a "customer" for selecting the customer who owns this instance of that model.
Both of the selectors result in field values that are complex object.
The
equipmentFormDataSchema is defined as
All of this mostly accomplishes what I want, but it leaves me with a Typescript error on the onBlur.
I'm not sure whether my issue has more to do with failing to understand my requirements, or how to apply Zod to those, or how to combine the Zod validator with TSF.11 Replies
vicious-goldOP•8mo ago
My
ModelSelectorField component eventually calls field.handleChange(model) with a fully-populated model. The component which uses that selector uses some of the data in model to determine which pieces of UI to expose. But ultimately, when I POST the form, I'm only persisting the modelNumber field from that object. Still, I like being able to have the complex data type result from the user selection interaction.
This is the Typescript complaint for the onBlur (although it actually works, it doesn't type check):
adverse-sapphire•8mo ago
so you start out with no reasonable value, and the complex selector will create the object you need? Is
null not a reasonable default value for this?
If it is, you could have the schema as nullable, transforming it into non-nullable and continuing with your validation.
defaultValues will be of type z.input<typeof schema>, that initial value being null describing no selection
if the description confuses you, I'm happy to provide a small example
also another thing to note:
* Zod needs to be above version 3.24 for standard schema support.
* You can pass the schema directly
vicious-goldOP•8mo ago
so you start out with no reasonable value, and the complex selector will create the object you needexactly correct.
null seems to be as reasonable a default as undefined which I'm currently using.
OK I see that I'm not being very clear on what I've done here. Maybe this is getting to my real problem.
This says that for the Model selector field validation, use the equipmentFormDataSchema its model field's schema definition. They're two different schemas, composed.
equipmentModelFormDataSchema defines the schema of the model field in the equipmentFormDataSchema. (But the field's schema is also used elsewhere in my app).adverse-sapphire•8mo ago
I see. I wasn't aware that you can access subschemas like that in zod, apologies.
exactly correct. null seems to be as reasonable a default as undefined which I'm currently using.And do you initiate
defaultValues as z.input<> and give it that default for the model field?vicious-goldOP•8mo ago
haha no apologies needed; I appreciate the interaction because it is forcing me to think more deeply about my problem so that I can explain it.
Currently, the defaultValues:
and over where the form data schemas are defined (at
src/lib/form-data.ts, because they're shared among components):
adverse-sapphire•8mo ago
tanstack form explicitly works with the input type, not the infer type from zod. Try and see if that fixes it
vicious-goldOP•8mo ago
👀
adverse-sapphire•8mo ago
infer vs. input tends to have problems with unions, refinements or transforms
vicious-goldOP•8mo ago
Yes, your recommendation helps alot. And now I can see that there's another issue (which I do already see how to fix).
The follow-up issue is that I've got alot of places in the component which refer to form state, e.g.
As you can see, I've had to add a type assertion because the type of
state.values.model is the untyped Object, {}. Which points my attention back to the definition of equipmentFormDataSchema.
The model field on this "equipment form data schema" doesn't really express my intent, which is that the thing either is "guaranteed" to be a well-formed object (of a "summary" type defined by the data-access layer), or it's undefined (or null, I don't think it matters too much which one). I don't actually need to reuse the form data schema of the "model form data schema" because that's not what's being validated here.
I suspected my problem had to do with an incomplete / incorrect "mental model", and discussing with you has helped me find that.adverse-sapphire•8mo ago
another thing that may be the cause is that your defaultValues is a partial of the form values
ideally it should just be of the schema type
so that necessity is probably because of what you said, where some values are not nullable when they should be
vicious-goldOP•8mo ago
ok, that made a big difference, including readability. Replaced the selectable fields with
z.object({}, {required_error: "X selection is required"}).passthrough().nullable(), and onblur: itsSchema.shape.x.unwrap()
Thanks again for the QSO