react-hook-form: Type 'Control' is not assignable to type 'Control'

This seems like a duplicate of #2984.

Describe the bug

I am experiencing this issue after following the Control example in your documentation and using any 7.x release. (have tried 7.0, 7.1, 7.2, 7.3 and patch versions of all)

I am calling useForm with a generic type in the shape of my form values – the error occurs whether I use a generic or not – and pass control to my components which wrap form values. My components accept a property control: Control per your example.

I get the error error TS2322: Type 'Control<FormValues>' is not assignable to type 'Control<FieldValues>'. Types of property 'register' are incompatible. and if I don’t assign a generic it will just read the object type e.g. Control<{ valuea: string, valueb: boolean }>.

To Reproduce Steps to reproduce the behavior:

  • Assign a set of form values to the generic input of useForm
  • Pass control to component which accepts Control type from react-hook-form
  • Witness issue

Codesandbox link (Required) https://codesandbox.io/s/nervous-rubin-pdh9g?file=/src/App.tsx

Expected behavior

I expect the generic type that I supply to useForm to be respected throughout the rest of the form interfaces as specified in the documentation.

Screenshots

image

Desktop (please complete the following information):

  • OS: MacOS
  • Browser: All browsers – fails basic TSC compilation
  • Version: 7.x

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 5
  • Comments: 15 (4 by maintainers)

Most upvoted comments

Hello ! I’m not quite sure I understand the problem entirely but if the goal is to have a generic component over the type of the useForm data structure, I think something like this should do the trick:

export interface IReactHookFormFieldProps<T> {
  name: FieldPath<T>;
  control: Control<T>;
  rules?: RegisterOptions<T>;
}

Here is a sandbox showing it with your code.


For fun I’ve made another one that ensure that the key passed to the component is a boolean

You can find this version here (If you’re interested)

Hope it can be helpful ! 😃

@jordan-jarolim Glad it helped ! 😃


You define an interface to expect T as generic but then you don’t pass it from the component

In this case TS will be able to infer the type of T based off the props. The only use-case I know about for using <Component<MyType> {...props} /> is when you when to opt out of TS compiler type inference which here isn’t the case.

Here is a great reference about that

it’s basically turning off TS check for Control<T> ?

I don’t really get what you mean by “turning off TS check”. With the defined interface, TS expect a prop control: Control<T>, T being a type that extends Record<string, any> which is the same constraint as the Control itself.

The one on the doc is wrong, just got it updated.

Screen Shot 2021-04-27 at 10 57 10 am
  1. useForm<MyType> in combination with control={(yourControlInstance as unknown) as Control<FieldValues>} works for me, its still just a workaround tho.
  2. I agree!
  3. I am not sure if we have the same issue here… if you don’t pass generic to useForm it takes FieldValues as default and this is the same for Control type. You can try to define you interface as control: Control<FieldValues>

I hope we will get some support on this 😃

Error in my previous comment occurred because I had an attribute on the component that wasn’t on the props of the component. Not sure why the error message was incorrect… but removing it fixed the issue for me.

Jordan, I was able to get item 1 working. While it is kludgy it will be acceptable for now.

I was unsuccessful not passing a generic to useForm even with Control<FieldValues> typing (not just Control sans generic).

Regarding item 2 (Generics in JSX) I think it would be useful for a more accurately representative example in codesandbox e.g. not containing both components in the same file. My particular implementation is being built for reuse, and so the customized FieldValues per form will not be able to simply be imported and used by the fields themselves.