How is the correct way to work with Vuex and typescript?

marcellorvalle picture marcellorvalle · Dec 17, 2018 · Viewed 11.2k times · Source

So far, the only information I found about the topic was this article.

I am trying to implement the store with 2 modules.

export interface RootState {
    /** root state props **/
}

const store: StoreOptions<RootState> = {
    modules: {
        foo,
        bar,
    },
};

export default new Vuex.Store<RootState>(store);

Then I have both modules:

export interface FooState {
    //(...)    
}

export const foo: Module<FooState, RootState> = {
    //(...)
};

export interface BarState {
    //(...)    
}

export const bar: Module<BarState, RootState> = {
    //(...)
};

All was ok until I had one situation where I needed a getter from foo module to access bar state:

export const getters: GetterTree<FooState, RootState> = {
    getInfo: (state, {}, rootState) => number {
        const value = rootState.bar.somevalue;
        //(...)
    },
};

I had a linting error explaining that rootState had no bar property. After some time thinking about it I managed to solve the error changing the original RootState interface:

export interface RootState {
    /** root state props **/
    foo: FooState;
    bar: BarState;
}

It solved the problem and was great for the IDE intellisense.

Is this aproach correct? To add all modules into the RootState interface used by StoreOptions?

Also, as it seems there is a lack of documentation about these typed interfaces (StoreOptions, Module, GetterTree, etc): Is Vuex mature enough to be used with typescript?

Edit: I forgot to mention: I still need to cast this.$store when acessing the store from a component (but could minimize it with vuex-class). It seems there is a question opened about it without answers. I suppose there is no other solution to this until now, am I right?

Answer

nicolidz picture nicolidz · Nov 26, 2019

Vuex is perfectly compatible with typescript using these vuex imports:

import {GetterTree, MutationTree, ActionTree} from "vuex"

The example below shows the easiest and most complete way to use vuex in typescript.

Principal store file:

import Vue from 'vue'
import Vuex from 'vuex'
import { GetterTree, MutationTree, ActionTree } from "vuex"
import MySubModule from '@/store/submodule'

Vue.use(Vuex)

class State {
    userId: string | null = null;
}

const getters = <GetterTree<State, any>>{
};

const mutations = <MutationTree<State>>{
    setUserId(state, payload) {
        state.userId = payload;
    }
};

const actions = <ActionTree<State, any>>{
    fetchUserId(store) {
    }
};

export default new Vuex.Store({
    state: new State(),
    mutations: mutations,
    actions: actions,
    modules: {
        subModuleName: MySubModule,
        //other submodules
    }
})

SubModule store file:

import { GetterTree, MutationTree, ActionTree } from "vuex"

class State {
}

const mutations = <MutationTree<State>>{
};

const actions = <ActionTree<State, any>>{
};

const MySubModule = {
    namespaced: true,
    state: new State(),
    mutations: mutations,
    actions: actions
};

export default MySubModule;

Hoping to help you !