mrcrowl / vuex-typex

Typescript builder for strongly-typed access to Vuex Store modules
MIT License
193 stars 22 forks source link

Proposal of ehancement #21

Closed victorgarciaesgi closed 5 years ago

victorgarciaesgi commented 5 years ago

Hi @mrcrowl

I wanted to share with you an upgrade I managed to create to vuex-typex with the help infer types from Typescript 2.8! I love your extension and I’m using it every day so I wanted to contribute to it!

Instead of committing or dispatching each function, I can just pass an Object regrouping all mutations

image

I’m prototyping it on my project and for the moment it’s working for the mutations. Here is a piece of code of how I managed to do that

type IsValidArg<T> = T extends object ? (keyof T extends never ? false : true) : true;

type inferMutations<T> = T extends (state, payload: infer P) => void
  ? IsValidArg<P> extends true
    ? (payload: P) => void
    : () => void
  : () => void;

export const storeBuilder = getStoreBuilder<any>();

export function stateBuilder<S>(state: S, name: string) {
  const { commit } = storeBuilder.module<S>(name, state);

  const registerMutations = <T>(mutations: T): { [K in keyof T]: inferMutations<T[K]> } => {
    Object.keys(mutations).map(m => {
      mutations[m] = commit(mutations[m]);
    });
    return mutations as any;
  };
  return { registerMutations };
}

By the way, it’s working when passing ‘any’ type! Still working on optional parameters

mrcrowl commented 5 years ago

That's an interesting approach! :) I hadn't seen infer types before.

If you F12 (Go to definition) on a usage of connectUser() does vs-code navigate you to the underlying function?

On Sat, 9 Mar 2019 at 05:42, Victor Garcia notifications@github.com wrote:

Hi @mrcrowl https://github.com/mrcrowl

I wanted to share with you an upgrade I managed to create to vuex-typex with the help infer types from Typescript 2.8! I love your extension and I’m using it every day so I wanted to contribute to it!

Instead of committing or dispatching each function, I can just pass an Object regrouping all mutations

[image: image] https://user-images.githubusercontent.com/15092120/54041957-544bda80-41c9-11e9-813f-3e017ee614e4.png

I’m prototyping it on my project and for the moment it’s working for the mutations. Here is a piece of code of how I managed to do that

type IsValidArg = T extends object ? (keyof T extends never ? false : true) : true;

type inferMutations = T extends (state, payload: infer P) => void

? IsValidArg

extends true

? (payload: P) => void

: () => void

: () => void;

export const storeBuilder = getStoreBuilder();

export function stateBuilder(state: S, name: string) {

const { commit } = storeBuilder.module(name, state);

const registerMutations = (mutations: T): { [K in keyof T]: inferMutations<T[K]> } => {

Object.keys(mutations).map(m => {

  mutations[m] = commit(mutations[m]);

});

return mutations as any;

};

return { registerMutations };

}

By the way, it’s working when passing ‘any’ type! Still working on optional parameters

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mrcrowl/vuex-typex/issues/21, or mute the thread https://github.com/notifications/unsubscribe-auth/ABtooKr42WWruDhYJ1uGp55yo6Sa9RhDks5vUpMKgaJpZM4bltjW .

victorgarciaesgi commented 5 years ago

@mrcrowl

Yeah juste tested it, it redirect directly on the initial function!

Also, i've managed to add actions to the list, I will try getters later!

mrcrowl commented 5 years ago

Sounds good. Ready for a pull-request! :)

On Mon, 11 Mar 2019 at 22:20, Victor Garcia notifications@github.com wrote:

@mrcrowl https://github.com/mrcrowl

Yeah juste tested it, it redirect directly on the initial function!

Also, i've managed to add actions to the list, I will try getters later!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mrcrowl/vuex-typex/issues/21#issuecomment-471462363, or mute the thread https://github.com/notifications/unsubscribe-auth/ABtooBVpYYAh9pwCO0YPt7k2Xa6y5zhmks5vVh_agaJpZM4bltjW .

victorgarciaesgi commented 5 years ago

I'm building a module function to do all the work at once!


export function VuexModule<
  S,
  M extends { [x: string]: (state, payload) => void },
  A extends { [x: string]: (context, payload) => any }
>(name: string, state: S, handlers: HandlersPayload<M, A>) {

  const { registerMutations, registerActions, state: newState } = stateBuilder(state, name);

  return {
    mutations: registerMutations(handlers.mutations),
    actions: registerActions(handlers.actions),
    state: newState
  }
}

const newModule = VuexModule('UserModule', state, {
  mutations: Mutations,
  actions: Actions
});
newModule.mutations.disconnectUser();
newModule.actions.checkUserSession()
victorgarciaesgi commented 5 years ago

Still not ready for a pull request aha, I'm testing things so i'll catch you up on the progression

victorgarciaesgi commented 5 years ago

@mrcrowl Okay I've finished and tested it. It works for actions, mutations, state and getters. It don"t support the 'name' argument yet.

Not sure on the naming though, do you have an idea instead of VuexModule?

export const UserModule = VuexModule('UserModule', state, {
  actions,
  mutations,
  getters,
});

image

It redirect very well to the underlying function

Also it will autocomplete accordingly on what you give to the function image

mrcrowl commented 5 years ago

How about something with a verb at the start like defineVuexModule() or just defineModule()? A capital letter at the start makes me think that it's a Class rather than a function.

On Tue, 12 Mar 2019 at 06:32, Victor Garcia notifications@github.com wrote:

@mrcrowl https://github.com/mrcrowl Okay I've finished and tested it. It works for actions, mutations, state and getters. It don"t support the 'name' argument yet.

Not sure on the naming though, do you have an idea instead of VuexModule?

export const UserModule = VuexModule('UserModule', state, { actions, mutations, getters, });

[image: image] https://user-images.githubusercontent.com/15092120/54144209-88bed100-442b-11e9-9294-98fa1e0fb7d3.png

It redirect very well to the underlying function

Also it will autocomplete accordingly on what you give to the function [image: image] https://user-images.githubusercontent.com/15092120/54144407-ece19500-442b-11e9-904a-b98db176bdbe.png

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/mrcrowl/vuex-typex/issues/21#issuecomment-471641650, or mute the thread https://github.com/notifications/unsubscribe-auth/ABtooD4ybEP-PxAvuczuH80qKnsR3IWIks5vVpMRgaJpZM4bltjW .

victorgarciaesgi commented 5 years ago

I like "defineModule". It's a bit long to do because i do it outside my work hours, but this will make my modules development a less messy!

victorgarciaesgi commented 5 years ago

@mrcrowl

I created a totaly new lib based on yours. Based on dynamic registration and allowing for dynamic modules! It takes mush less boilerplate to declare your modules!

Would love if you tested it! :)