Default value breaks types
Describe the bug and the expected behavior
When using for example zod discriminated union for form schema, providing default value breaks the types completely.
Conform version
v1.0.2
Steps to Reproduce the Bug or Issue
https://stackblitz.com/edit/github-qiy4lh-vn8142?file=app%2Froutes%2Ftype-inference.tsx
What browsers are you seeing the problem on?
No response
Screenshots or Videos
No response
Additional context
No response
From what I understand, the defaultValue must exactly match the schema type which is a bit cumbersome and breaks other things.
A workaround I found is to fallback all string values to ?? "" even if they are optional, but that's cumbersome as well π
It looks like Typescript is trying to infer the types from both defaultValue and onValidate. I think this will be best solved by the NoInfer which is still on beta π
. Let me check if there is another approach that can work with earlier version.
A temporary solution is to set the type manually to stop typescript from inferring it.
const [form, fields] = useForm<z.input<typeof schema>>({
// ...
});
Yeah I've already tried to apply NoInfer directly in the conform source code but to no avail π I'll try your approach
Typescript seems to infer the type correctly if you spread over the defaultValues instead of passing it to the useForm hook directly:
const [form, fields] = useForm({
lastResult,
onValidate({ formData }) {
return parseWithZod(formData, { schema: LinkPageFormSchema });
},
defaultValue: {
...defaultValues
},
});
@edmundhung, I've done my best to create an isolated reproduction of the problems here: TypeScript Playground
As you can see, in most places schema type inference is working exactly opposite of what's expected. For example, if you hover over the last useForm call, you can see the first two type arguments are reversed; the inferred Schema type comes from defaultValue, while the inferred FormValue type comes from schema. This matches the behaviour I've been seeing locally.
Thankfully, passing explicit type arguments always works as expected, which I've also demonstrated in the reproduction. So for now, this is what we'll do in our codebase.
What's truly maddening is that on line 18, if you switch FormOptions<Schema, FormValue> to FormOptions<FormValue, Schema>, 6 of the 7 error cases are resolved! I have no idea why this works, because it definitely shouldn'tβit is absolutely backwards. And yet, somehow, it makes up for almost every incorrect type inference. π€·