resolvers: Problem with yupResolver when one type in useForm generic is optional

Describe the bug When we provide optional key in useForm generic we getting error TS2322: Type 'Resolver<{ name: string | null | undefined; age: number; }>' is not assignable to type 'Resolver<{ name: string; age?: number | undefined; }, any>'.   Types of parameters 'values' and 'values' are incompatible.     Type '{ name: string; age?: number | undefined; }' is not assignable to type '{ name: string | null | undefined; age: number; }'.       Types of property 'age' are incompatible.         Type 'number | undefined' is not assignable to type 'number'.           Type 'undefined' is not assignable to type 'number'.

To Reproduce Steps to reproduce the behavior:

  • create new react project with vite
  • create simple form wit useForm() and in generic add one optional key for example age?: number
  • create yup schema with all details
  • attach created schema to yupResolver
  • we have a problem

Codesandbox link (Required) https://codesandbox.io/s/quirky-fog-3695px?file=/src/TestView.tsx

Expected behavior Works without problem

Screenshots image

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Reactions: 18
  • Comments: 15 (5 by maintainers)

Most upvoted comments

I have a case that this auto infer feature seems not good at all. Before I can just pass the values and defaultValues conveniently like this image But now, TS keeps complaining, that’s really annoying because we know that we pass somewhat the same type it expects image image

The schema is your single source of truth so

SubmitHandler<Yup.InferType<typeof form>>

https://github.com/jquense/yup#getting-started

You don’t need to manually type useForm from:

const { register } = useForm<{ name: string; age?: number }>({
    resolver: yupResolver(form)
  });

to

const { register } = useForm({
    resolver: yupResolver(form)
  });

Types are inferred from the schema

You don’t need to manually type useForm from:

const { register } = useForm<{ name: string; age?: number }>({
    resolver: yupResolver(form)
  });

to

const { register } = useForm({
    resolver: yupResolver(form)
  });

Types are inferred from the schema

I honestly hate this change, I prefer to have typescript autocomplete inside the Yup.object because writing typescript is readable, by infering from a schema sucks especially in a pattern where I am prepopulating the form and only some data is required to be validated.

This would mean that if with this new format you do not define every single key even those that do not need validating breaks the inference of hook form, meaning register(“name”) gets no more autocomplete for things no defined in Yup schema. And sure you can do yupResolver<Yup.anyObject> but then I still will not have no autocomplete within the schema itself which is what I desire most because looking at the docs and knowing what key to navigate by looking vs my backender that can just send me a quicktype.io interface with the structure is very annoying.

I prefer my yup to infer from the form than the other way around.

I got by this issue by passing a generic parameter to yupResolver with the infered type.

resolver: yupResolver<MyInferedType>(MySchema)

We basically lost typings on our forms and now to get those typings back we need to add a workaround, and all I wanted to do was be able to use yup.lazy on yupResolver.

@khuongtp I’ve solved it by removing template argument for useForm but as I see you are not using it, make sure your version is 3.1.1 and maybe clean the project

@jorisre ok good but how i can now access to form values? I just need pass interface which looks like our schema to SubmitHandler or there is some different way to do that?

Here is the updated release note, sorry for the mistake, it should be at least a minor version instead of a patch

https://github.com/react-hook-form/resolvers/releases/tag/v3.1.1