react-hook-form: Typings for `errors` and `validationResolver` are very restrictive

Is your feature request related to a problem? Please describe. Both errors and validationResolver make strong assumptions about the format of the errors (when using TypeScript, of course). The project page says it supports a variety of validation libraries (none of which I use) or custom validation. I partially rely on ajv and partially write my own validation. In both cases I use completely flat errors (e.g. { "cases[0].caseData.profileInformation.age": "should be a number" }), which is incompatible with the typings enforced by the library. So I feel like (at least with TypeScript) it does not actually support using custom validation. Or is there a technical reason why errors need to be shaped a certain way? AFAIC errors are created and consumed by user-code only and the library only passes it around?

Describe the solution you’d like I think it would be good to allow a third, optional type being passed to useForm which indicates the error object shape. It could default to the current type (which seems to work fine for a variety of use cases).

Describe alternatives you’ve considered I’ve resorted to using a bunch of as any casts and sometimes tricking the TypeScript compiler by combining untyped objects with not using the dot notation (which is bad style in the end), e.g.

  const errors = {}
  if (!values.caseSetId) {
    // eslint-disable-next-line dot-notation
    errors['caseSetId'] = 'Select a case set'
  }

But this doesn’t work when I want to put an error on an array field. It will always want an array of errors, which IMHO doesn’t make sense if I simply want to say “Please add at least one X”

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 18 (12 by maintainers)

Commits related to this issue

Most upvoted comments

I’ve just run into a similar issue trying to type my form with a Material-UI Multiple Select field

Brief example and full codesandbox is below:

interface Values {
  multiSelect: string[];
}
...
const { errors } = useForm<Values>();
const multiSelectError = errors.multiSelect?.message // Property 'message' does not exist on type 'FieldError[]'.

https://codesandbox.io/s/focused-napier-hiwvc?file=/src/App.tsx

The errors typing seems to assume any array values are always multiple fields whereas in my case it’s a single field with an array for it’s value.

@bluebill1049 I will look into this later 👍

https://github.com/react-hook-form/react-hook-form/issues/1421#issuecomment-614483053

Unfortunately, It is no way in TypeScript to recognize that it is any array value. Because we supported nest object since v4 as follows:

type FormValues = {
  nested: {
    object: {
      key: string;
    };
    array: number[];
  };
}

const { register, errors } = useForm<FormValues>();

errors.nested?.object?.key?.message // no error
errors.nested?.array?.[0]?.message // no error
errors.nested?.array?.[0]?.message // no error

<input name="nested.object.key" ref={register({ required: 'required' })} />
<input name="nested.array[0]" ref={register({ required: 'required' })} />
<input name="nested.array[1]" ref={register({ required: 'required' })} />

If expected the field name to be nested.object and the field value to be { key: string }, TypeScript would not be able to recognize { key: string } as the field value. That is a headache problem… If TypeScript solves this issue https://github.com/microsoft/TypeScript/issues/12754, we can define the perfect type.

You can use any[] to avoid this problem as follows:

interface Values {
  multiSelect: any[];
}

Or, we may need to reconsider the creation of an external utility type to identify the value of the field I previously proposed https://github.com/react-hook-form/react-hook-form/issues/987#issuecomment-587256304.

interface Values {
  multiSelect: FormValue<string[]>;
}

Related:

After discussion with @kotarella1110 (our TS custodian) we both agree to introduce another generic (third) for error type is not trivial and also not intuitive to new/existing users as well. We probably will have to use any for situation when form value is not having a 1 to 1 relationship with error. However, if you have a strong opinion about this third generic, we are open to PR as well, and happy to take a look at it.