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

Improve getValidatedFormData type inference #61

Merged
merged 1 commit into from
Dec 13, 2023

Conversation

mintchkin
Copy link
Contributor

@mintchkin mintchkin commented Dec 9, 2023

Description

Small update that should allow inferring the schema type from the resolver type when calling getValidatedFormData or validateFormData.

Partially fixes #55, though there's still an annoying upstream issue in @hookform/resolvers that causes zodResolver() to lack type inference as was called out in this comment (some other resolvers e.g. yupResolver should work fine)

Before:

const schema = z.object({ username: z.string(), password: z.string() });
const resolver = zodResolver(schema);

export const action = async ({ request }: ActionFunctionArgs) => {
  const data = await getValidatedFormData<z.infer<typeof schema>>(request, resolver);
  // ...
}

After:

const schema = z.object({ username: z.string(), password: z.string() });

// this annotation is still required for zod because of an upstream bug in @hookform/resolvers
const resolver: Resolver<z.infer<typeof schema>> = zodResolver(schema);

export const action = async ({ request }: ActionFunctionArgs) => {
  const data = await getValidatedFormData(request, resolver);
  // ...
}

Type of change

Please delete options that are not relevant.

  • Bug fix (non-breaking change which fixes an issue)

Checklist:

  • My code follows the guidelines of this project
  • I have performed a self-review of my own code

@mintchkin
Copy link
Contributor Author

fwiw, I also pushed a PR to @hookform/resolvers that would allow full inference for zod resolvers when it's coupled with this one

const schema = z.object({ username: z.string(), password: z.string() });
const resolver = zodResolver(schema);

export const action = async ({ request }: ActionFunctionArgs) => {
  // data is appropriately typed here
  const data = await getValidatedFormData(request, resolver);
  // ...
}

@AlemTuzlak
Copy link
Contributor

@mintchkin thank you for this! So the generic is passed to the resolver and it should work as long as the upstream supports type inference?

@mintchkin
Copy link
Contributor Author

@AlemTuzlak yeah exactly, the Resolver<> type in react-hook-form accepts a generic argument for the shape of the object it returns, so it's possible to go

const schema = z.object({ ... })                    // -> Schema<T>
const resolver = zodResolver(schema)                // -> Resolver<T>
const result = getValidatedFormData(req, resolver)  // -> Promise<T>

without losing any type information, as long as zodResolver() and getValidatedFormData() are good about forwarding the T generic along the chain. unfortunately they both drop it right now, but this PR fixes that for getValidatedFormData() and the upstream PR fixes it for zodResolver()

@AlemTuzlak AlemTuzlak merged commit 45e8bf9 into forge42dev:main Dec 13, 2023
@AlemTuzlak
Copy link
Contributor

@mintchkin awesome, thank you for this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[suggestion] Implicit Inference of Form Schema in getValidatedFormData and validateFormData
2 participants