【问题标题】:Vuex store type with Typescript带有 Typescript 的 Vuex 存储类型
【发布时间】:2019-04-07 23:03:54
【问题描述】:

我正在尝试让 Vuex 商店对 Typescript 友好。我正在按照here 的说明建造商店。但是,当我从组件访问 this.$store 时,类型为 Store<any>

我不知道如何更改它,使其默认为 Store<MyState> 而无需每次都进行强制转换。

【问题讨论】:

    标签: typescript vue.js vuex


    【解决方案1】:

    如果有人遇到这个问题 - 我们通过重新定义构造函数返回的类型来解决这个问题 -

    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;
    

    然后我们就

    export default VueStrong.extend({
        name: 'name',
    
        components: {
            componentA,
            componentB,
    },
    

    这让我们可以正确使用打字:

    methods: {
    sessionStarted(): Boolean | undefined {
        return this.$store.state.sessionState?.session.started;
    },
    

    【讨论】:

    • 你知道是否有办法让输入与 this.$store.getters 一起工作?
    • @maembe 不幸的是,我不这么认为——你可能会真正喜欢枚举和一些泛型,但这感觉比手动投射更糟糕。 =\
    【解决方案2】:

    不幸的是,不可能用更具体的类型覆盖由 VueX 类型定义的 Store&lt;any&gt; 类型。我能想到的最好方法是添加第二个字段,该字段返回 $store 但类型正确,因此您不必在任何地方使用强制转换或在所有组件中声明它:

    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,
    });
    

    【讨论】:

      【解决方案3】:

      您可以在组件中声明一个属性,以便打字稿应用打字。我一直将它用于$refs,但它也适用于$store。除了用 ! 标记之外,您不需要对属性做任何事情。操作符告诉编译器 vue 会为你设置变量。

      $store!: Store<StoreStateType>;
      

      我使用的另一种方法是使用MapStateMapGetters 组件助手。他们为您创建属性,以便您可以在模板中使用它们。示例:

      @Component({
        computed: mapState({
          userFullName: (state: any) => state.user.fullName,
          userEmail: (state: any) => state.user.email
        })
      })
      

      不要忘记导入 Store、您的 vuex 状态类和您使用的任何帮助器 import { Store, mapState } from "vuex";

      【讨论】:

        【解决方案4】:

        没有一个答案让我满意。我做了一些挖掘,发现了这个小宝石。在我的store.ts 文件中,我只是添加:

        declare module "@vue/runtime-core" {
          interface ComponentCustomProperties {
            $store: Store<State>;
          }
        }
        

        所以看起来更像这样:

        //store.ts
        import { createStore, Store } from "vuex";
        import { CustomTool, CustomListType } from "custom";
        
        export type State = {
          tool: CustomTool
          list: CustomListType | null
        };
        
        export default createStore({
          state: {
            tool: CustomTool.Empty
            list: null,
          } as State,
          mutations: {},
          actions: {},
          modules: {}
        };
        
        declare module "@vue/runtime-core" {
          interface ComponentCustomProperties {
            $store: Store<State>;
          }
        }
        

        使用 vue3 和 typescript 4.4。

        【讨论】:

          猜你喜欢
          • 2021-07-02
          • 1970-01-01
          • 1970-01-01
          • 2019-12-19
          • 2018-07-21
          • 1970-01-01
          • 2021-11-02
          • 2019-01-26
          • 2022-08-19
          相关资源
          最近更新 更多