vuex-module-decorators icon indicating copy to clipboard operation
vuex-module-decorators copied to clipboard

Strongly typing commit and dispatch

Open hisuwh opened this issue 3 years ago • 1 comments

Loving your package. Its great for calling my vuex module from within my components but its biggest drawback is calling other actions and mutations from within the module itself. I've actually got a solution for this working in my project but it would be a breaking change to - introducing a new generic type and breaking calling other modules.

import { ActionContext, CommitOptions, DispatchOptions, Payload } from "vuex";
import { VuexModule } from "vuex-module-decorators";

export type KeysOfType<T, K> = { [I in keyof T]: T[I] extends K ? I : never }[keyof T];

interface EnhancedDispatch<T> {
    <K extends KeysOfType<T, (arg: any) => any>>(type: K, payload?: Parameters<T[K]>[0], options?: DispatchOptions): Promise<any>;
    <P extends Payload>(payloadWithType: P, options?: DispatchOptions): Promise<any>;
}

interface EnhancedCommit<T> {
    <K extends KeysOfType<T, (arg: any) => any>>(type: K, payload?: Parameters<T[K]>[0], options?: CommitOptions): void;
    <P extends Payload>(payloadWithType: P, options?: CommitOptions): void;
}

interface EnhancedContext<T, S, R> extends ActionContext<S, R> {
    dispatch: EnhancedDispatch<T>;
    commit: EnhancedCommit<T>;
}

export class EnhancedVuexModule<T, S, R = any> extends VuexModule<S, R> {
    public context: EnhancedContext<T, S, R>;
}

With this code you gain strong typing when calling commit (and dispatch):

image

It does have a few issues:

  • It requires an additional generic argument to specify the class of your module which would be a breaking change
  • We can't infer which functions are commit and dispatch so you could still call the wrong type of function from commit or dispatch
  • Trying to commit or dispatch to another module would cause a compilation error, and require doing something like (I quite like the semantics of this):
this.context.commit<any>("otherModule/mutation", myPayload);

Of course you could include the above types in addition to your existing types and give consumers the choice. Let me know your thoughts and I can send a PR if you would like.

hisuwh avatar Dec 15 '20 10:12 hisuwh

I have written a commit function which accepts the method and the module to add typing. If you're interested I could share the code or do a PR. It's just an addon, so no breaking changes needed.

Ansaal avatar Jun 05 '21 17:06 Ansaal