Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default value breaks types #478

Open
jansedlon opened this issue Feb 22, 2024 · 5 comments
Open

Default value breaks types #478

jansedlon opened this issue Feb 22, 2024 · 5 comments
Labels
bug Something isn't working

Comments

@jansedlon
Copy link
Contributor

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

@jansedlon
Copy link
Contributor Author

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 😅

@edmundhung
Copy link
Owner

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>>({
   // ...
});

@jansedlon
Copy link
Contributor Author

jansedlon commented Feb 22, 2024

Yeah I've already tried to apply NoInfer directly in the conform source code but to no avail 😂
I'll try your approach

@edmundhung edmundhung added the bug Something isn't working label Feb 22, 2024
@edmundhung
Copy link
Owner

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
    },
});

@aaronadamsCA
Copy link
Contributor

aaronadamsCA commented Mar 3, 2024

@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. 🤷

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants