Home > Net >  How to type hint a vue component method using Vue 2 with Composition API
How to type hint a vue component method using Vue 2 with Composition API

Time:03-15

I have two components <Modal> and <App> and I want to call a method of the Modal component. The code works when adding @ts-ignore, but TypeScript is complaining. I'm using Vue2 with Composition API.

Simplified example (I'm leaving out app initialization):

Modal.vue

<template>
   <div ref="modalEl">I'm the modal<slot></slot></div>
</template>
<script lang="ts">
import {defineComponent, onMounted, ref} from '@vue/composition-api';
import Modal from 'bootstrap/js/dist/modal';

export default defineComponent({
    setup(props) {
       const modalEl = ref<Element | string>('');

       onMounted(() => {
          modal = new Modal(modalEl.value);
       });

       const show = () => modal.show();

       return {
          modalEl,
          show,
       } 
    }
});
</script>

App.vue

<template>
   <div>
       <Modal ref="modalSave">I'm modal content</Modal>
       <button @click="showModal">show modal</button>
   </div>
</template>
<script lang="ts">
import {ref,defineComponent} from '@vue/composition-api';
import Modal from 'Modal.vue';
export default defineComponent({
  components: {
      Modal
  },
  setup(props) {
      const modalSave = ref<InstanceType<typeof Modal> | null>(null);
      const showModal = () => modalSave.value?.show();

      return {
          modalSave,
          showModal
      }
  }
});

</script>

As mentioned, it works and I get even code completion in PhpStorm. But when I'm compiling I get the error:

ERROR in App.vue.ts(115,24) TS2339: Property 'show' does not exist on type '{ readonly $el: Element; readonly $options: { data?: DefaultData | undefined; props?: string[] | { [x: string]: Prop | { type?: Prop | Prop[] | undefined; required?: boolean | undefined; default?: any; validator?: ((value: any) => boolean) | undefined; } | Prop<...>[]; } | undefined; ... 35 more ...'.

Does anyone know how to make TypeScript happy here without adding ts-ignore?

CodePudding user response:

You will need to use defineExpose (docs):

<!-- MyModal.vue -->
<script setup lang="ts">
<template>
   <div ref="modalEl">I'm the modal<slot></slot></div>
</template>
<script lang="ts">
import {defineComponent, onMounted, ref} from '@vue/composition-api';
import Modal from 'bootstrap/js/dist/modal';

export default defineComponent({
    setup(props) {
       const modalEl = ref<Element | string>('');

       onMounted(() => {
          modal = new Modal(modalEl.value);
       });

       const show = () => modal.show();

       defineExpose({ show });            
  • Related