I\'m trying to get a Vuex store to be Typescript friendly. I\'m building the store as explained here. However, when I access this.$store
from a component, the t
You could declare a property in your component so typescript will apply typing. I use this for $refs
all the time but it works for the $store
too. You don't need to do anything with the property apart from marking it with ! operator to tell the transpiler that vue will set the variable for you.
$store!: Store<StoreStateType>;
Another alternative I use is to use the MapState or MapGetters component helpers. They create the properties for you so you can use them in the template. Example:
@Component({
computed: mapState({
userFullName: (state: any) => state.user.fullName,
userEmail: (state: any) => state.user.email
})
})
Don't forget to import the Store, your vuex state class and any helper you use import { Store, mapState } from "vuex";
.
Unfortunately it is impossible to override the Store<any>
type that is defined by the VueX types with a more specific type. The best I could come up with was to add a second field that returns $store
but properly typed so you don't have to use casts everywhere or declare it in all your components:
import { Store } from "vuex";
// Type the $tstore properly, which is the same as $store but properly typed.
// Unfortunately you cannot override the Store<any> type.
declare module "vue/types/vue" {
interface Vue {
$tstore: Store<State>;
}
}
// Set $tstore to be a getter that simply returns $store.
Object.defineProperty(Vue.prototype, "$tstore", {
get: function() {
return this.$store as Store<State>;
},
enumerable: true,
});
If anyone comes across this - we got around this issue by redefining the type that the constructor returned -
import Vue, { VueConstructor } from 'vue'
import { Store } from 'vuex'
import { RootState } from '@/store/types'
abstract class VueStrongClass extends Vue {
public $store!: Store<RootState>
}
const VueStrong = Vue as VueConstructor<VueStrongClass>;
export default VueStrong;
and then we just
export default VueStrong.extend({
name: 'name',
components: {
componentA,
componentB,
},
which lets us then use typing properly:
methods: {
sessionStarted(): Boolean | undefined {
return this.$store.state.sessionState?.session.started;
},