Please help with Vuex4 / TS store module setup

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

export 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!

I’ll be honest with you, I stopped reading through your post about half way because all the files were overwhelming, so I’d say yes it’s over engineered. I know that’s not very helpful for your specific TS issue, but I found it too much effort to reason about and therefore too difficult to try to debug.

The way I’ve always built my Vuex modules is as contained modules with all the state, getters, actions, mutations, and typings (unless they’re shared) in one file. That way I know that each module has everything I need while I’m working in it and I’m not searching around for different files. If I need to change something related to the User store, I just go and look for store/User.ts, simple as that.

You might consider taking this approach which in turn may help you resolve your TS issues - sorry I can’t be of more help with that part. Best of luck!

@JamesThomson yes, sorry, you are right. I updated my question to lower the amount of code …