Inquiring about Vue 3 with TypeScript and Enhancing Types for Compatibility with Plugins

I've been struggling to find a working example of how to implement type augmentation with Vue3 and TypeScript. I have searched for hours without success, trying to adapt the Vue2 documentation for Vue3.

It appears that the Vue object in the vue-class-component module needs to be augmented, but I'm unsure how to do it.

This is similar to my current implementation:

Any advice or guidance would be greatly appreciated.

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");

Answer №1

Based on my understanding, it seems that vue-class-component is not fully compatible with Vue 3 yet. There are ongoing discussions regarding modifications needed in the library. Therefore, it is uncertain if the examples provided below will function properly with it. Nonetheless, I have made some adjustments to enhance 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" {
  //Binding to `this` keyword
  interface ComponentCustomProperties {
    $hello: IHelloModule;
  }
}

I have defined the type within the plugin file itself, but you also have the option to define them in the shims-vue.d.ts file.

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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide to developing a custom plugin for Nuxt.js

This is the content of my rpc.js plugin file: const { createBitcoinRpc } = require('@carnesen/bitcoin-rpc') const protocol = 'http' const rpcuser = 'root' const rpcpassword = 'toor' const host = '127.0.0.1&apo ...

Modifying state within reducers is not allowed

Encountered the following error while using @ngrx/store: index.js?4b23:19 State mutation is prohibited inside of reducers. (anonymous) @ index.js?4b23:19 (anonymous) @ index.ts:54 rootReducer @ index.ts:70 _initialStateFactory @ ng2.ts?2a33:24 AppModule ...

When accessing from the frontend (Angular), the User.FindFirst(ClaimTypes.NameIdentifier) method does not return any values

I'm encountering a new issue - just as the title suggests. I've managed to identify where the problem occurs but I'm unable to resolve it. Let's start from the beginning. In the backend (ASP.NET 3.0), I have a class AuthController with ...

Create duplicates of both the array and its individual elements by value

I'm having trouble figuring out how to properly copy an array along with all its elements. In my model, I have a name and options, both of which are strings. This is what I currently have: const myArrayToDuplicate = [myModel, myModel, myModel] My ...

NUXT: ERROR Unexpected export token encountered while running npm dev command

I am relatively new to using nuxt and currently working on my first website with it. I encountered an error that I am struggling to resolve. My WSL Ubuntu development environment was functioning properly until I mistakenly ran npm run build instead of npm ...

Exporting constants using abstract classes in TypeScript files

In my Typescript files, I've been exporting constant variables like this: export const VALIDATION = { AMOUNT_MAX_VALUE: 100_000_000, AMOUNT_MIN_VALUE: 0, DESCRIPTION_MAX_LENGTH: 50, }; My constant files only contain this one export without any ...

Enhancing your Vue.js component props with descriptive hints

I am currently integrating new components into a project and I want to include information about a specific prop, such as hints or acceptable values that can be passed. Is there a way for my component to display this information when users press ctrl+space ...

billboard.js: The 'axis.x.type' property is conflicting with different data types in this context

axis: { x: { type: "category" } }, An issue has arisen: The different types of 'axis.x.type' are not compatible with each other. The value of 'string' cannot be assigned to '"category" | &qu ...

What is the process of inserting a sparkline chart into a Kendo Angular grid?

I am attempting to display a bullet chart in the first column of my grid. <kendo-grid-column> <ng-template kendoChartSeriesTooltipTemplate let-value="value"> <div> <kendo-sparkline [data]="bulletData" type="bullet" [ ...

Synchronization between Vue and Node API on the go

Ensuring continuous synchronization with the backend API is crucial. What modifications made in the backend should automatically update the frontend in Vue? How can we achieve constant syncing with the API? Is setting intervals and calling the API the mo ...

`How can TypeScript be used to designate the type of a variable within the useState hook?`

I defined a variable called 'text' and a hook named 'setText'. I'm using them to update the value of a form input field. How can I ensure that 'text' is always of type string? This is what I attempted: interface TextInt ...

Building chat rooms using VueJS

For my project, I am developing a Queue System using Node (SocketIO), VueJS, and MySQL. The goal is to automatically create a new chat room once 5 people have joined the queue. I already have the main chat component created, but now I need to figure out ...

The confusion arises from the ambiguity between the name of the module and the name of

In my current scenario, I am faced with the following issue : module SomeName { class SomeName { } var namespace = SomeName; } The problem is that when referencing SomeName, it is pointing to the class instead of the module. I have a requireme ...

Tips for ensuring the correct typing of a "handler" search for a "dispatcher" style function

Imagine having a structure like this: type TInfoGeneric<TType extends string, TValue> = { valueType: TType, value: TValue, // Correspond to valueType } To prevent redundancy, a type map is created to list the potential valueType and associate i ...

What is the best way to transform this component into a function rather than a class?

import React, { Component } from "react"; class ChatHistory extends Component { render() { const messages = this.props.chatHistory.map((msg, index) => ( <p key={index}>{msg.data}</p> )); return ( <div ...

What causes an error during the compilation of an Angular package containing a singleton class?

I am currently in the process of creating an Angular library. Within this library, I have developed a singleton class to manage the same SignalR connection. Here is the code implementation: import * as signalR from '@microsoft/signalr'; export c ...

How can you eliminate the prop that is injected by a Higher Order Component (HOC) from the interface of the component it produces

In my attempt to create a Higher Order Component, I am working on injecting a function from the current context into a prop in the wrapped component while still maintaining the interfaces of Props. Here is how I wrap it: interface Props extends AsyncReque ...

Error type inferred by TypeScript

I am currently in the process of learning TypeScript, and I encountered some errors in the code below: Error: Unexpected token. A constructor, method, accessor, or property was expected. [ts] Declaration or statement expected. class duckType{ public ...

Vue lightweight loading CSS error: "Undefined property 'denominator'"

Within my project, I have a style.less file that I am loading in the following manner: import "./styles/styles.less"; The contents of the file are structured as shown below. I had to encapsulate the styles to prevent them from affecting the rest of the p ...

"Can someone guide me on the steps to host my Laravel Project on Google Firebase? I

Currently, I am working on a project that involves using Vue.js for the front end, Laravel for the back end, and MySQL for the database. I successfully deployed the Vue.js portion to Google Firebase, but now I'm facing issues with the functionality re ...