TypeScript Support
Vuex provides its typings so you can use TypeScript to write a store definition. You don't need any special TypeScript configuration for Vuex. Please follow Vue's basic TypeScript setup to configure your project.
However, if you're writing your Vue components in TypeScript, there're a few steps to follow that require for you to correctly provide typings for a store.
Typing $store
Property in Vue Component
Vuex doesn't provide typings for this.$store
property out of the box. When used with TypeScript, you must declare your own module augmentation.
To do so, declare custom typings for Vue's ComponentCustomProperties
by adding a declaration file in your project folder:
// vuex.d.ts
import { Store } from 'vuex'
declare module '@vue/runtime-core' {
// declare your own store states
interface State {
count: number
}
// provide typings for `this.$store`
interface ComponentCustomProperties {
$store: Store<State>
}
}
Typing useStore
Composition Function
When you're writing your Vue component in Composition API, you will most likely want useStore
to return the typed store. For useStore
to correctly return the typed store, you must:
- Define the typed
InjectionKey
. - Provide the typed
InjectionKey
when installing a store to the Vue app. - Pass the typed
InjectionKey
to theuseStore
method.
Let's tackle this step by step. First, define the key using Vue's InjectionKey
interface along with your own store typing definition:
// store.ts
import { InjectionKey } from 'vue'
import { createStore, Store } from 'vuex'
// define your typings for the store state
export interface State {
count: number
}
// define injection key
export const key: InjectionKey<Store<State>> = Symbol()
export const store = createStore<State>({
state: {
count: 0
}
})
Next, pass the defined injection key when installing the store to the Vue app:
// main.ts
import { createApp } from 'vue'
import { store, key } from './store'
const app = createApp({ ... })
// pass the injection key
app.use(store, key)
app.mount('#app')
Finally, you can pass the key to the useStore
method to retrieve the typed store.
// in a vue component
import { useStore } from 'vuex'
import { key } from './store'
export default {
setup () {
const store = useStore(key)
store.state.count // typed as number
}
}
Under the hood, Vuex installs the store to the Vue app using Vue's Provide/Inject feature which is why the injection key is an important factor.
Simplifying useStore
usage
Having to import InjectionKey
and passing it to useStore
everywhere it's used can quickly become a repetitive task. To simplify matters, you can define your own composable function to retrieve a typed store:
// store.ts
import { InjectionKey } from 'vue'
import { createStore, useStore as baseUseStore, Store } from 'vuex'
export interface State {
count: number
}
export const key: InjectionKey<Store<State>> = Symbol()
export const store = createStore<State>({
state: {
count: 0
}
})
// define your own `useStore` composition function
export function useStore () {
return baseUseStore(key)
}
Now, by importing your own composable function, you can retrieve the typed store without having to provide the injection key and its typing:
// in a vue component
import { useStore } from './store'
export default {
setup () {
const store = useStore()
store.state.count // typed as number
}
}