Enhanced support for Vuex store in Visual Studio Code

I am currently developing an application using Vue.js 2, Vuex, and TypeScript within Visual Studio Code. I have the Vetur extension installed to enhance my development experience. While I have managed to set up intellisense for most of my project with a definition file, I am struggling to add my Vuex store to the intellisense setup. Despite reading through the Definition Documentation, I still can't seem to figure out how to achieve intellisense for items under `this.$store`. Although Vetur provides intellisense for things like `state` and `getters`, it doesn't extend to the next level (e.g., `this.$store.state.TestVariable`). So, my main question is, how can I enable intellisense for my Vuex store?

Contract Management Store


        import Vue from 'vue';
        import Vuex from 'vuex';

        Vue.use(Vuex);

        export default new Vuex.Store({
            state: {
                Contract: new Library.Model.Entity.Contract()
            }
        });
    

Contract Component


        <template>
            <contract-line></contract-line>
        </template>

        <script lang="ts">
            import Vue from 'vue';
            import Vuex from 'vuex';
            import store from '../store/ContractManagementStore';
            import ContractLine from "./ContractLine.vue";

            export default Vue.extend({
                name: 'contract-management',
                store,
                components: {
                    'contract-line': ContractLine
                }
            });
        </script>

        <style>

        </style>
    

Contract Line Component


        <template>
            <button v-if="CanDelete"></button>
        </template>

        <script lang="ts">
            import Vue from 'vue';
            import Vuex from 'vuex';

            Vue.use(Vuex);

            export default Vue.extend({
                computed:{
                    CanDelete(): Boolean {
                        // Looking for intellisense after this.$store.state.
                        return this.$store.state.Contract.ContractStatus.Value === Library.Enums.ContractStatus.Draft
                    }
                }
            });
        </script>

        <style>

        </style>
    

Answer №1

To ensure proper type consistency, it is recommended to explicitly define your state.

Inside the Contract Management Store.ts

export interface ContractManagementState {
    Contract: ContractType;
}

Within your Component:

...
(this.$store as Store<ContractManagementState>).<intellisense here>

Each time you access the state in this manner, you will need to apply this approach. This requirement stems from Vuex leveraging module augmentation to declare the existence of the $store property to TypeScript.

Referencing to vuex/types/vue.d.ts:

declare module "vue/types/vue" {
  interface Vue {
    $store: Store<any>;
  }
}

You are unable to directly substitute the 'any' with specific state typings (due to the nature of module augmentation). One potential workaround is to utilize getters for accessing your Store. Various TypeScript libraries are available for adding type information to getters, mutators, and actions, such as vuex-typescript and vuex-typex.

Answer №2

In the past couple of days, I have been struggling with a frustrating lack of typing-awareness when dealing with this.$store.state.

Thanks to @georg-grab 's solution, I found inspiration.

  1. Although I am not well-versed in TypeScript, this solution may seem basic but it gets the job done.
  2. Please note that my solution is specifically tailored for handling this.$store.state; other references like this.$store.dispatch do not benefit from IntelliSense.
// store/index.ts
// Omitting details on vuex modules; refer to Vuex documentation.
import Vue from 'vue'
import Vuex, {Store} from 'vuex'

import auth, {State as AuthState} from './modules/auth'  // State interface defined within module.

export interface State {
  auth: AuthState
}

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    auth
  }
}) as Store<State>  // Explicitly declare as Store<State> instead of Store<any>.

To enhance functionality, include a global instance getter using a Vue plugin:

// main.ts
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store, { State } from './store'

declare module 'vue/types/vue' {  // Specify type of this.$state as 'State'
  interface Vue {
    $state: State
  }
}
const TypedState = {  
  install(Vue: any) {  
    Object.defineProperty(Vue.prototype, '$state', { 
      get (): State { return store.state as State }  
    })
  }
}
Vue.use(TypedState)

Now enjoy accessing values in this.$store.state seamlessly through this.$state while benefiting from IntelliSense.

I have also attempted to modify the interface of vm.$store (from Store<any> to Store<State>), but unfortunately TypeScript doesn't provide a straightforward solution:

declare module 'vue/types/vue' {
  interface Vue {
    $store: Store<State>   // Error
  }
}

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

Best Practices for Error Handling in Typescript

After delving into articles about error handling, a thought lingers in my mind - is throwing an exception on validation logic in the value object really the most efficient approach? Take for example this class that represents a value object: export class U ...

Ways to stop dialog from disappearing in Reactjs

This code snippet demonstrates the implementation of a popup with buttons, where clicking the cancel button triggers a confirmation dialog. To make the popup disappear when clicked outside of it, the following event handling is employed: const popupRef = ...

Tips for accessing data from a local JSON file in your React JS + Typescript application

I'm currently attempting to read a local JSON file within a ReactJS + Typescript office add-in app. To achieve this, I created a typings.d.ts file in the src directory with the following content. declare module "*.json" { const value: any; ex ...

Tips for efficiently loading data in a sequence using rxjs: within each sequence, there could be multiple calls made

const dates = [{start:'03/06/2020', end: '03/09/2020'}, {start:'03/12/2020', end: '03/03/2021'}, ...] const fetchData = service.get(page = 1, dates[0]) and service.get(page = 2, dates[0]) retrieves the necessary d ...

Image with responsive div buttons

I am trying to add a set of buttons on each image in my masonry image gallery, but I'm facing issues with responsiveness. Whenever I resize the screen, some of the buttons disappear instead of adjusting their size and position accordingly. I want th ...

The TypeScript error "Issue with Type Assertion: 'This expression is not callable Type'...' has no call signatures" occurs when there is a missing semicolon

Here's a simplified version of our original code: const start: number = 10 const end: number = 20 (someElement as HTMLInputElement).setSelectionRange(start, end) We encountered an error with the 20, where a red squiggly line appeared indicating ...

A guide on refreshing the dependencies list within Angular's node modules and package.json files

A close friend sent me the angular src folder, which I used to create a new Angular project. However, when I replaced my newly created src folder with my friend's and tried running the application using npm start, I encountered errors related to missi ...

Need help restarting a timer I've built in Angular with just a click?

I am in the process of developing a compact application that will help me keep track of my activities within a specific time frame. Once I input an activity into a field and click "OK," it should be added to a list. My current challenge lies in resetting ...

Testing Angular with Jasmine: The spy should have been called as expected

Seeking assistance for a persistent issue that has been troubling me. I am currently working on unit tests for a component I developed, and no matter what I try, I can't seem to resolve the recurring problem of an "Expected spy getTopRatedMedia to ha ...

Dealing with GraphQL mutation errors without relying on the Apollo onError() function

When managing access to an API call server-side, I am throwing a 403 Forbidden error. While trying to catch the GraphQL error for a mutation, I experimented with various methods. (Method #1 successfully catches errors for useQuery()) const [m, { error }] ...

Ways to prevent a user from reaching a specific page by entering the URL in a react and typescript application

Is there a way to restrict access to a specific page with the URL "myurl/view"? I want only admin users to be able to view this page, while preventing other users from accessing it. Currently, when the view button is clicked, it redirects to the URL "/vie ...

Using constant variables as arguments in functions in TypeScript

While learning about TypeScript, I encountered some confusion regarding how it handles const variables. Let's consider a scenario where I define an interface for a number: interface MyNumber { value: number; } If I then create a constant MyNumbe ...

Encountering the "potential null object" TypeScript issue when utilizing template ref data in Vue

Currently, I am trying to make modifications to the CSS rules of an <h1> element with a reference ref="header". However, I have encountered a TypeScript error that is preventing me from doing so. const header = ref<HTMLElement | null> ...

Understanding the Purpose of the Pipe Function in Angular 2 and Typescript Observables

Recently, I encountered a situation where I needed to accept an Observer parameter in a function written in Typescript. I struggled to find a solution, reminding me of working with a delegate parameter in C#. The specific scenario involved adding a bookend ...

Mastering Generic Types in Functions in Typescript

My current structure looks like this: export interface Complex { getId<T>(entity: T): string } const test: Complex = { getId<Number>(entity){return "1"} // encountering an error 'entity is implicitly any' } I am wondering w ...

What could be causing TypeScript to forego type inference and default to 'any' in this scenario?

While refactoring parts of our React app in TypeScript, I encountered a challenge that required me to use what I consider to be a less than ideal double type argument. I'm unsure if this is a bug in TypeScript or if there is some type ambiguity causin ...

When I receive a 404 response from the API, I aim to start my observable

How can I trigger my observable initialization when receiving a 404 response from the API? The code snippet below is not working as expected. const urlParams = { email: this.email }; this.voicesProfileObservable$ = this.service.request<any>( AVAI ...

employing a variable within a function that is nested within another function

I'm encountering an issue where I am using a variable within a nested function. After assigning a value to it, I pass it to the parent function. However, when I call the function, nothing is displayed. function checkUserExists(identifier) { let user ...

Typescript is issuing warnings when displaying errors for the RTK query

I am currently using React Ts and Rtk query. My goal is to display the API response error on the UI. While it's working, I am encountering a warning that prompts me to set an error type for the response errors. How can I incorporate an error type for ...

Expanding the capabilities of i18next's translation function

I'm having trouble properly extending the function. I am stuck with the error Cannot redeclare block-scoped variable t. I am unsure if declaring a module is the correct approach (I am new to TypeScript). I have also tried creating a wrapper for the t ...