65.9K
CodeProject is changing. Read more.
Home

Correctly Typing Vuex with TypeScript

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3 votes)

May 5, 2021

CPOL

1 min read

viewsIcon

22313

downloadIcon

196

A walkthrough of statically typing Vuex with TypeScript

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:

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:

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.

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:

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 ...

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