1

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!

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

21 Comments

sorry, I can't find RootState. Do I have to create it on my own? E.g. export type RootState = {};
That's correct.
Hm unfortunately the code doesn't work for me. I can't register the getters, this is the code with the error message: pastebin.com/ngMpvbDA
The order should be opposite, fixed.
thanks for help. Based on next.vuex.vuejs.org/guide/… I'm trying to register the module and use it inside a component but unfortunately it seems the registration is wrong and my getter returns an undefined value. This is the updated code pastebin.com/YbSgKqmm
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.