Vuex store type with Typescript

前端 未结 3 1741
暗喜
暗喜 2021-01-11 09:41

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

相关标签:
3条回答
  • 2021-01-11 09:57

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

    0 讨论(0)
  • 2021-01-11 10:08

    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,
    });
    
    0 讨论(0)
  • 2021-01-11 10:17

    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;
    },
    
    0 讨论(0)
提交回复
热议问题