Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Question about Vue 3 + TypeScript and Augmenting-Types-for-Use-with-Plugins

Does anyone know of a working example of how the type augmentation should be implemented with Vue3 and TypeScript? I have been trying follow the Vue2 docs in hoops of using the same in Vue3 with no success and spend the past 3 hours of searching without any results.

It seems that the Vue object in the vue-class-component module should be augmented to work,but how?

My implementation is similar to the following:

Any advice?

https://v2.vuejs.org/v2/guide/typescript.html#Augmenting-Types-for-Use-with-Plugins

import { App, Plugin } from "vue";

export interface IHelloModule {
  sayHello: (name: string) => string;
}

export const helloPlugin: Plugin = (app: App, options) => {

  const helloModule:IHelloModule = {

    sayHello: function(name: string) {
      return `Hello ${name}`;
    }

  };

  app.provide("$hello", helloModule);
};
import { Vue } from 'vue-class-component';
import { IHelloModule } from "@/hello";

declare module "vue/types/vue" {
  interface Vue {
    $hello: IHelloModule;
  }
}

declare module "vue/types/vue" {
  interface VueConstructor {
    $auth: IHelloModule;
  }
}
<template>
  <div class="home">
     .....
  </div>
</template>

<script lang="ts">
import { Options, Vue } from 'vue-class-component';

@Options({
  components: {
  },
})
export default class Home extends Vue {
  mounted() {
    console.log(this.$hello.sayHello("World"))
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^
                     Neither TS nor vue-cli recognize this
  }
}
</script>
import { createApp } from "vue";
import App from "./App.vue";
import { helloPlugin } from "./hello";
import router from "./router";

createApp(App)
  .use(router, helloPlugin)
  .mount("#app");

like image 290
gevik Avatar asked Mar 02 '23 00:03

gevik


1 Answers

For what I understand, vue-class-component doesn't fully supports Vue 3 yet. They're still discussing modifications in the library. So, I don't know if the examples below will work with it, but this is what I've done to augment plugin types.

hello.plugin.ts

import { App } from "vue";

export interface IHelloModule {
  sayHello: (name: string) => string;
}

export default {
  install: (app: App) => {
    const helloModule: IHelloModule = {
      sayHello: function(name: string) {
        return `Hello ${name}`;
      }
    }; 

    app.config.globalProperties.$hello = helloModule;
  }
}

declare module "@vue/runtime-core" {
  //Bind to `this` keyword
  interface ComponentCustomProperties {
    $hello: IHelloModule;
  }
}

I declared the type in the plugin file itself, but you can declare them in the shims-vue.d.ts file too.

main.ts

import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import Hello from "./hello.plugin";

createApp(App)
  .use(router)
  .use(Hello)
  .mount("#app");

Hello.vue

<script lang="ts">
import { defineComponent } from "vue";

const Hello = defineComponent({
  mounted() {
    console.log(this.$hello.sayHello("World"));
  }
});

export default Hello;
</script>
like image 70
A.Terra Avatar answered Mar 04 '23 22:03

A.Terra