Skip to content

How create mapping from main Store and Modules at once? #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Suruat opened this issue Apr 28, 2019 · 9 comments
Open

How create mapping from main Store and Modules at once? #1

Suruat opened this issue Apr 28, 2019 · 9 comments

Comments

@Suruat
Copy link

Suruat commented Apr 28, 2019

First of all, thank you for this great plugin!

When I try to use mappings it only autocomplete either module or a store (depending on what type I've provided to createHelper function).
Is it possible to enable data from all modules and main store in one mapping function?

Thank you in advance!

@ClickerMonkey
Copy link
Owner

You can import { mapState } from 'vuex-typescript-interface' (or other mapping functions) to get the mapping functions you need for store + modules (the default Vuex stuff). The Vuex syntax uses special strings to be able to reference modules and therefore cannot be type safe at this time.

If there were a small function custom to this library that somehow allowed mapping from the store and sub modules, do you think that would be worth the few extra bytes in your build?

@Suruat
Copy link
Author

Suruat commented Apr 29, 2019

@ClickerMonkey , thanks for a quick respond.

If there were a small function custom to this library that somehow allowed mapping from the store and sub modules, do you think that would be worth the few extra bytes in your build?

Yeah, I think few bytes is nothing comparing with more strait and user-friendly API of the package.

@jaredmcateer
Copy link

Is there any progress on namespaced module support? I'd like very much to use this package as it seems to be the most lightweight way of adding type safety to vuex, without drastically modifying the code, and the easiest to migrate to Vuex 4 once that is released but we rely pretty heavily on ns modules.

@ClickerMonkey
Copy link
Owner

ClickerMonkey commented Aug 15, 2019

I'm working on it now, hopefully I have an acceptable solution soon. My solution doesn't modify vuex at all, but tricks your TypeScript code into having types associated to namespace paths.

You'll have to do something like this:

// use to be: 'named/module' or 'named/module/variable'

// returns string under hood but carries all type information
path<IRootStore>().module('named').module('module');
path<IRootStore>().module('named').module('module').state('variable');

@ClickerMonkey
Copy link
Owner

The only thing I won't be able to provide is support for something like this:

methods: {
  ...mapActions([
    'rootAction',
    'namedModule/namedAction'
  ])
}
// this.rootAction(payload)
// this['namedModule/namedAction'](payload)

That's because the result of that mapping makes rootAction and namedModule/namedAction methods on the Vue component - and Typescript doesn't have support for string concatenation of types. You would have to do:

const storePath = path<IRootStore>();
// ...
methods: {
  ...mapActions(storePath, ['rootAction']),
  ...mapActions(storePath.module('namedModule'), ['namedAction'])
}
// this.rootAction(payload)
// this.namedAction(payload)

@jaredmcateer
Copy link

jaredmcateer commented Sep 23, 2019

I see you merged this back into master in August but have not published to npm yet, is there anything I can do to help this along?

Edit:

I've done some testing off the master branch and I've run into an issue. Using something like:

  export interface PanelStore {
    namespaced: true;

    hidden: Record<string, boolean>;
    readonly hiddenByKey: (panelKey: string) => boolean;
    setHidden(payload: {panelKey: string; isHidden: boolean}): Promise<void>;
    SET_HIDDEN(payload: {panelKey: string; isHidden: boolean}): void;
  }

  export interface RootStore {
    modules: {
      panels: PanelStore
    }
  }
const key = "mainPanel";
const hiddenByKey = path<RootStore>().module('panels').getter('hiddenByKey').get();
store.getters[hiddenByKey](key);

I get the error: [tsserver 2538] [E] Type 'GetterPath<PanelStore, RootStore, "hiddenByKey", (panelKey: string) => boolean>' cannot be used as an index type.

I don't know if there is anything that could be done about that.

@ClickerMonkey
Copy link
Owner

I had to do some magic to get it to sort of work. I stopped working on it because the version of TypeScript I was working on it with just couldn't handle what needed to be done, no matter what crazy solution I came up with. The current Magic has types like GetterPath - but really that value is actually a string. I had to carry type information somehow, and this was the only thing I could do at the moment.

You might be able to just do hiddenByKey as string as ugly as that is, hopefully you don't have to do hiddenByKey as unknown as string.

Sorry this has ben so delayed, TypeScript can be pretty powerful, but it definitely has it's limits. An expert on types might be able to solve the problem, but I'm pretty spent on it.

@jaredmcateer
Copy link

Too bad to hear, I appreciate the effort you put in, it's well above my current level of competence for TS. I think I'll just suffer without proper type safety until the next version.

@ClickerMonkey
Copy link
Owner

With TS 4.1.0 I should be able to get complete support for namespaced modules without using the path functions I created. We should be able to use plain strings - that TS will validate to an actual commit/dispatch/etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants