Click here to Skip to main content
15,881,832 members
Articles / Web Development / Vue.js
Tip/Trick

Correctly Typing Vuex with TypeScript

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
5 May 2021CPOL1 min read 21.4K   196  
A walkthrough of statically typing Vuex with TypeScript
TypeScript is a great alternative of JavaScript, and works really well with frontend frameworks like Vue.js. However in the beginning, it can be hard to get the static types right. Sadly, it is not written in the official documentation how to do this. Luckily, with a little experimentation, I managed to do it.

Our Example Vuex Store

In this tip, I will create a Vuex store for storing apples and oranges. Apples and oranges will have their own separate module, and the root store will aggregate these two.

The Apple Module

Let's look at the first implementation of the Apple module at @/store/AppleModule.ts:

TypeScript
import { Apple } from "@/models/Apple";

export interface ApplesState {
    items: Array<Apple>
}

export default {
    namespaced: true,
    state: (): ApplesState => ({
      items: Array<Apple>()
    }),
    mutations: {
        setApples: function(state: ApplesState, apples: Array<Apple>): void {
          state.items = apples;
        }
    }
}

This module has a single property in its state, an array of apples, and a single mutation, that sets this array. The type of the state is declared by the ApplesState interface, which is used as the state parameters type in the mutation.

Let's include this module in the root store at @/store/intex.ts:

TypeScript
import Vue from 'vue'
import Vuex from 'vuex'
import appleModule, { ApplesState } from './AppleModule'

Vue.use(Vuex)
export interface State {
  apples: ApplesState;
}

export default new Vuex.Store<State>({
  modules: {
    apples: appleModule
  }
})
We declare the type of the root state with the State interface. We use the State as type parameter on the Vuex.Store instance.

Actions and Context

To define actions in the store module, we need to have a Context type. For this, we will need to import the root state type into our apple module, and use it to define the Context type.

TypeScript
import { ActionContext } from "vuex";
import { State } from '.';

type Context = ActionContext<ApplesState, State>;

You can now use this Context type for the context parameter in the action definitions:

TypeScript
loadApples: async function(context: Context): Promise<Array<Apple>> {
  const apples = (await axios.get('apples')).data;
  context.commit('setApples', apples);
  return context.state.items;
}

Orange Module

The orange module is implemented similarly to apples. They are not like apples and oranges after all ...

TypeScript
import Vue from 'vue'
import Vuex from 'vuex'
import appleModule, { ApplesState } from './AppleModule'
import orangeModule, { OrangesState } from './OrangeModule'

Vue.use(Vuex)

export interface State {
  apples: ApplesState;
  oranges: OrangesState;
}

export default new Vuex.Store<State>({
  modules: {
    apples: appleModule,
    oranges: orangeModule
  }
})

History

  • 4th May, 2021: First version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer Code Sharp Kft.
Hungary Hungary
Making webshops faster at codesharp.dev

Comments and Discussions

 
-- There are no messages in this forum --