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
eastern-cyanOP•5mo 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):
continuing-cyan•5mo 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
eastern-cyanOP•5mo 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).continuing-cyan•5mo 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?eastern-cyanOP•5mo 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):
continuing-cyan•5mo ago
tanstack form explicitly works with the input type, not the infer type from zod. Try and see if that fixes it
eastern-cyanOP•5mo ago
👀
continuing-cyan•5mo ago
infer vs. input tends to have problems with unions, refinements or transforms
eastern-cyanOP•5mo 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.continuing-cyan•5mo 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
eastern-cyanOP•5mo 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