如何使用带有 Vuex 和 TypeScript 的 Vue 3 设置商店模块?

How to setup a store module using Vue3 with Vuex4 and TypeScript?

我想使用 TypeScript 进入 Vue3 / Vuex4,但不幸的是文档没有太大帮助

https://next.vuex.vuejs.org/guide/typescript-support.html

作为初学者,我从一个简单的问题跟踪存储模块开始。在我的问题模块中,我创建了一个 index.ts 文件,其中包含“全局存储实例”并自行注册

import {
  ActionContext,
  ActionTree,
  GetterTree,
  MutationTree,
  Store,
} from "vuex";

export default (store: Store<{}>): void => {
  store.registerModule("issues", {
    namespaced: true,
    state,
    getters,
    actions,
    mutations,
  });
};

export type Issue = {
  title: string;
  isOpen: boolean;
  createdAt: Date;
};

export type State = {
  issues: Issue[];
};

export type Getters = {
  issues(state: State): Issue[];
};

export type ActionAugments = Omit<ActionContext<State, State>, "commit"> & {
  commit<K extends keyof Mutations>(
    key: K,
    payload: Parameters<Mutations[K]>[1]
  ): ReturnType<Mutations[K]>;
};

export enum ActionType {
  SubmitIssue = "SubmitIssue",
}

export type Actions = {
  [ActionType.SubmitIssue](
    context: ActionAugments,
    submitIssuePayload: SubmitIssuePayload
  ): void;
};

export type SubmitIssuePayload = {
  issueTitle: string;
};

export enum MutationType {
  SubmitIssue = "SUBMIT_ISSUE",
}

export type Mutations = {
  [MutationType.SubmitIssue](state: State, payload: SubmitIssuePayload): void;
};

const state: State = {
  issues: [],
};

const getters: GetterTree<State, State> & Getters = {
  issues: function (state: State): Issue[] {
    return state.issues;
  },
};

const actions: ActionTree<State, State> & Actions = {
  [ActionType.SubmitIssue]: function (
    { commit }: ActionAugments,
    { issueTitle }: SubmitIssuePayload
  ): void {
    commit(MutationType.SubmitIssue, { issueTitle });
  },
};

const mutations: MutationTree<State> & Mutations = {
  [MutationType.SubmitIssue]: function (
    state: State,
    { issueTitle }: SubmitIssuePayload
  ): void {
    const issue: Issue = {
      title: issueTitle,
      isOpen: true,
      createdAt: new Date(),
    };

    state.issues.push(issue);
  },
};

目前由于某些原因我坚持设置:

.

No overload matches this call.
  Overload 1 of 2, '(path: string, module: Module<State, {}>, options?: ModuleOptions | undefined): void', gave the following error.
    Type 'GetterTree<State, State> & Getters' is not assignable to type 'GetterTree<State, {}> | undefined'.
      Type 'GetterTree<State, State> & Getters' is not assignable to type 'GetterTree<State, {}>'.
        'string' index signatures are incompatible.
          Type 'Getter<State, State>' is not assignable to type 'Getter<State, {}>'.
            Property 'issues' is missing in type '{}' but required in type 'State'.
  Overload 2 of 2, '(path: string[], module: Module<State, {}>, options?: ModuleOptions | undefined): void', gave the following error.
    Argument of type 'string' is not assignable to parameter of type 'string[]'.ts(2769)
store.ts(26, 3): 'issues' is declared here.
index.d.ts(132, 3): The expected type comes from property 'getters' which is declared here on type 'Module<State, {}>'

这是有道理的,因为全局存储实例的类型是 Store<{}> 并且我的模块似乎期望 Store<State>

我该如何解决这个问题?

感谢帮助!

问题是模块状态类型指定在需要根状态的地方,但它们并不相同。

最好将根状态类型保留为单独的类型并导入,而不是像 {} 那样对其进行硬编码,因为它会随时间变化。

应该是store: Store<RootState>GetterTree<State, RootState>等,其中根状态泛型参数影响Vuex上下文中rootState的类型。