简体   繁体   中英

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

I want to get into Vue3 / Vuex4 using TypeScript but unfortunately the docs didn't help much

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

As a beginner, I started with a simple issue tracking store module. Inside my issues module I created a index.ts file taking in the “global store instance” and registers itself

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

Currently I'm stuck with the setup for some reasons:

  • I copypasted the ActionAugments from Google. Do I really need to reinvent the ActionContext on my own to get access to the commit function?
  • The setup is not correct yet. The function store.registerModule shows this error

.

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, {}>'

which makes sense, because the global store instance is of type Store<{}> and my module seems to expect Store<State>

How would I fix this?

Thanks for help!

The problem is that module state type was specified in places where root state is expected, while they aren't same.

It's preferable to keep root state type as separate type and import instead of hardcoding it like {} because it can change with time.

It should be store: Store<RootState> , GetterTree<State, RootState> , etc. Where root state generic parameter affects the type of rootState in Vuex context.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM