vee-validate icon indicating copy to clipboard operation
vee-validate copied to clipboard

Typescript error when using `useForm` `errors`

Open HydraCOREY opened this issue 3 years ago • 3 comments

What happened?

I'm getting a Typescript error "Element implicitly has an 'any' type because expression of type 'registrants[${number}].firstName' can't be used to index type". image

Reproduction steps

  1. Use useFieldArray (example: registrants with fields email, firstName, lastName)
  2. Use a v-if to check if there is an error for the field array field. (example: v-if="errors[registrants[${idx}].email]")
  3. Try building the project.
  4. Get error in build:
error TS7053: Element implicitly has an 'any' type because expression of type '`registrants[${number}].email`' can't be used to index type 'Partial<Record<"state" | "name" | "city" | "street" | "zipCode" | "registrants", string | undefined>>'.

324                       v-if="errors[`registrants[${idx}].email`]"

I have my code in codesandbox below. I don't know how to use codesandbox, but the working code is in the HelloWorld component.

Version

Vue.js 3.x and vee-validate 4.x

What browsers are you seeing the problem on?

  • [X] Firefox
  • [X] Chrome
  • [X] Safari
  • [X] Microsoft Edge

Relevant log output

(property) errors: Partial<Record<"name" | "street" | "city" | "state" | "zipCode" | "registrants", string | undefined>>
Element implicitly has an 'any' type because expression of type '`registrants[${number}].firstName`' can't be used to index type 'Partial<Record<"name" | "street" | "city" | "state" | "zipCode" | "registrants", string | undefined>>'.ts(7053)

Demo link

https://codesandbox.io/s/cranky-breeze-80lujr?file=/src/App.vue

Code of Conduct

  • [X] I agree to follow this project's Code of Conduct

HydraCOREY avatar May 26 '22 21:05 HydraCOREY

This is a known limitation, at the moment the field names are inferred for the root keys only. So you might need to use casting to any here.

I'm unsure if it is possible for TypeScript to convert nested paths into a path string with array support. I will take a look into it but probably will take sometime.

logaretm avatar May 27 '22 00:05 logaretm

@logaretm I tried adding any to errors.

const { handleSubmit, errors: any } = useForm({ validationSchema: schema})

But now I get a different error of:

any
Property 'errors' does not exist on type '{ $: ComponentInternalInstance; $data: {}; $props: Partial<{}> & 
Omit<Readonly<ExtractPropTypes<{}>> & VNodeProps & AllowedComponentProps & ComponentCustomProps, never>; ... 
10 more ...; $watch(source: string | Function, cb: Function, options?: WatchOptions<...> | undefined): WatchStopHandle; } & ... 
4 more ... & Co...'.

Any suggestions? Did I cast the type in the wrong place?

HydraCOREY avatar May 27 '22 11:05 HydraCOREY

What you did is you've renamed the errors to any. You can cast it in a couple of spots:

const { handleSubmit, errors } = useForm({ validationSchema: schema})

// use `formErrors` instead of errors in the template
const formErrors = errors as any;

Or cast them in the template:

 v-if="(errors as any)[`registrants[${idx}].email`]"

logaretm avatar May 27 '22 13:05 logaretm

You can reference errors with . paths now. There is an issue that still needs fixing here. But this is mostly addressed now.

logaretm avatar Jul 30 '23 14:07 logaretm