ClickerMonkey / vuex-typescript-interface

Adding magical type safety to Vuex without additional code
MIT License
44 stars 4 forks source link

Usage with nuxt.js #6

Closed mrkswrnr closed 5 years ago

mrkswrnr commented 5 years ago

First of all: Thank you for this library! I also tried to make vuex typesafe and must admit that I really like your approach - maybe even better than mine!

We are using vuex a lot in combination with nuxt.ts and I wanted to share some thoughts about using your library with nuxt.js:

1. Using the interfaces with vuex modules mode:

import R from "~/store";

export default interface S {
  // module declaration
}

// Variant a:
type M = Module<S, R>;

export const state: M["state"] = () => ({});
export const mutations: M["mutations"] = {};
export const getters: M["getters"] = {};
export const actions: M["actions"] & ThisType<Store<M>> = {};

// Variant b:
export const state: Resolvable<StateInputFor<S>> = () => ({});
export const mutations: MutationTree<S> = {};
export const getters: GetterTree<S, R> = {};
export const actions: ActionTree<S, R> & ThisType<Store<M>> = {};

Maybe you could declare a shorter type for Resolvable<StateInputFor<S>> to make it more readable.

2. ThisType of ActionTree should be Store<S>

Vuex actions are bound to the store. Therefore the ThisType in an ActionHandler is Store<S>. Currently you have to merge the type with ThisType<Store<M>> to make accessing injections like $axios work.

Maybe you could add this to your declaration to make it work out of the box.

3. Workaround for namespaced modules:

While we are waiting for microsoft/TypeScript#12754 to be implemented in Typescript, one could use the following workaround:

// store/a.ts
import R from '~/store/index';

export default interface S {
  callBAction(payload): Promise<void>;
}

export const actions: ActionTree<S, R> = {
  async callBAction({ dispatch }, payload) {
    dispatch("b/action", payload, { root: true });
  }
};
// store/b.ts
export default interface S {
  action(payload): Promise<void>;
}
// store/index.ts
import BStore from '~/store/b';
export interface S {
   "b/action": BStore["action"]
}

While this is nothing special it might help somebody to use namespace modules without big modifications.

4. Subsequent declarations

See my comment in #5

I hope my comments are understandable and you can use them to further improve your great library.

Thank you!

ClickerMonkey commented 5 years ago
  1. I can do that (make a shorter type)
  2. Can do (although not official, it is implemented this way)
  3. I am working on the namespace issue in a feature branch.
  4. Thanks for bringing this to my attention. Look in #5 for my workaround.
mrkswrnr commented 5 years ago
  1. Thank you!
  2. Again: thank you :-) ThisType was added in vuex@3.1.0: feat: add type annotation for the context of actions and mutations
  3. Great to hear that!
  4. See #5

If there is anything I can contribute, please let me know.

ClickerMonkey commented 5 years ago

Resolved with v1.0.2

  1. Will be resolved with #1