【发布时间】:2019-04-07 23:03:54
【问题描述】:
我正在尝试让 Vuex 商店对 Typescript 友好。我正在按照here 的说明建造商店。但是,当我从组件访问 this.$store 时,类型为 Store<any> 。
我不知道如何更改它,使其默认为 Store<MyState> 而无需每次都进行强制转换。
【问题讨论】:
标签: typescript vue.js vuex
我正在尝试让 Vuex 商店对 Typescript 友好。我正在按照here 的说明建造商店。但是,当我从组件访问 this.$store 时,类型为 Store<any> 。
我不知道如何更改它,使其默认为 Store<MyState> 而无需每次都进行强制转换。
【问题讨论】:
标签: typescript vue.js vuex
如果有人遇到这个问题 - 我们通过重新定义构造函数返回的类型来解决这个问题 -
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;
},
【讨论】:
不幸的是,不可能用更具体的类型覆盖由 VueX 类型定义的 Store<any> 类型。我能想到的最好方法是添加第二个字段,该字段返回 $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,
});
【讨论】:
您可以在组件中声明一个属性,以便打字稿应用打字。我一直将它用于$refs,但它也适用于$store。除了用 ! 标记之外,您不需要对属性做任何事情。操作符告诉编译器 vue 会为你设置变量。
$store!: Store<StoreStateType>;
我使用的另一种方法是使用MapState 或MapGetters 组件助手。他们为您创建属性,以便您可以在模板中使用它们。示例:
@Component({
computed: mapState({
userFullName: (state: any) => state.user.fullName,
userEmail: (state: any) => state.user.email
})
})
不要忘记导入 Store、您的 vuex 状态类和您使用的任何帮助器 import { Store, mapState } from "vuex";。
【讨论】:
没有一个答案让我满意。我做了一些挖掘,发现了这个小宝石。在我的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。
【讨论】: