Vetur: Property 'validate' does not exist on type 'Vue'.Vetur(2339)

Created on 4 Sep 2019  路  6Comments  路  Source: vuejs/vetur

  • [ x] I have searched through existing issues
  • [x ] I have read through docs
  • [x ] I have read FAQ

Info

  • Platform: macOS
  • Vetur version: 0.22.2
  • VS Code version: 1.37.1
  • Vee-Validate 3.0.3

Problem

Screenshot 2019-09-04 at 17 00 29

Reproducible Case

  1. Install vee-validate 3.0.3 for form input validation
  2. Use a ValidationObserver to validate your entire form
  3. Use a ValdationProvider on a form input
  4. Create a button with a click listener and a submit function attached or use the form submit
  5. In the submit function try to call the validate() function of the observer (vee-validate)
invalid

Most helpful comment

You need to annotate a type for it. Vetur and TypeScript does not (cannot) infer it for you.

interface YourComponentType extends Vue {
  validate(): void
}

@Component
class YourComp extends Vue {
  $refs!: {
    observer: YourComponentType
  }

  method() {
    this.$refs.observer.validate()
  }
}

All 6 comments

You need to annotate a type for it. Vetur and TypeScript does not (cannot) infer it for you.

interface YourComponentType extends Vue {
  validate(): void
}

@Component
class YourComp extends Vue {
  $refs!: {
    observer: YourComponentType
  }

  method() {
    this.$refs.observer.validate()
  }
}

Vee-validate 3 is entirely re-written in typescript and has all type annotations included. It does not make any sense to me to make changes in my code to tell Vetur about working code that it is actually working code... It shouldn't give me an error when there is no error in the first place!

It cannot infer the $refs type to actual component because ref resolution is done out of TypeScript code. There is nothing we can do about it on Vetur side. That's why we need to manually annotate it to notify the type to TypeScript compiler.

In the future, the template ref syntax will be changed more type friendly way. We can define refs shorter way with it.
https://vue-composition-api-rfc.netlify.com/api.html#template-refs

If you want a fully typed version of @ktsn's answer you can replace YourComponentType with the following code snippet:

import { ValidationProvider } from 'vee-validate';

type ProviderInstance = InstanceType<typeof ValidationProvider>;

interface VeeValidateObserverRef extends Vue {
  subscribe(subscriber: any, kind?: string): void;
  unsubscribe(id: string, kind?: string): void;
  validate(options?: { silent?: boolean }): Promise<boolean>;
  reset(): void;
  restoreProviderState(provider: ProviderInstance): void;
  removeProvider(id: string): void;
  setErrors(errors: Record<string, string[]>): void;
}

You need to annotate a type for it. Vetur and TypeScript does not (cannot) infer it for you.

interface YourComponentType extends Vue {
  validate(): void
}

@Component
class YourComp extends Vue {
  $refs!: {
    observer: YourComponentType
  }

  method() {
    this.$refs.observer.validate()
  }
}

You can make this more generic by:

interface vExtType extends Vue {
  [k:string]: any
}

@Component
class YourComp extends Vue {
  $refs!: {
    observer: vExtType,
    anyOther: vExtType
  }

  method() {
    this.$refs.observer.validate();
    this.$refs.anyOther();
    ...
  }
}

How can we implement this in composition-api plugin? Say we have

export default defineComponent({
    setup() {
        const formRef = ref<any>(null); // any for now

        function login() {
            const valid = formRef.value.validate();
            // undefined
        }

        return {
            formref
        }
    }
})
Was this page helpful?
0 / 5 - 0 ratings