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