gertqin / vuex-class-modules

Typescript class decorators for vuex modules
MIT License
194 stars 20 forks source link

How to access Store extensions in 'this' instance? #43

Open Arsync opened 4 years ago

Arsync commented 4 years ago

Within vanilla Vuex we have extension like

// vuex-shims.d.ts
declare module 'vuex/types' {
    interface Store<S> {
        $api: ServiceFactory;
    }
}

And access it in actions like

async [ActionNames.DoSomething]() {
  await this.$api.doSomething(); // 'this' known as Store<R> type and $api is registered extension.
}

But module of 'vuex-class-modules' has no 'this' as Store type. How to access $api extension?

Tried to make extended subclass of VuexModule like

export class AugmentedVuexModule extends VuexModule
{
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    protected store: Store<any>;

    constructor(options: RegisterOptions)
    {
        super(options);
        this.store = options.store;
    }
}

Usage:

@Action
async doSomething()
{
    await this.store.$api.doSomething();
}

But it cause an error:

/ -> error during render
RangeError: Maximum call stack size exceeded
bodograumann commented 4 years ago

I would propose that you provide the service factory directly to your vuex class module:

@Module
class MyModule extends VuexModule {
  constructor(private api: ServiceFactory, options: RegisterOptions) {
    super(options);
  }
}

export const myModule = new MyModule(api, { store, name: "myModule" });

Yes, that means you have to explicitely provide the service factory to every module that needs it. This approach works well with dependency injection (e.g. InversifyJS) though.

Arsync commented 4 years ago

Something wrong with this implementation:

@Module
export default class EmployeeProfileModule extends VuexModule
{
    private api: ServiceFactory; // Works fine, while 'identity' field commented

    private identity: IdentityManager; // <-- this one cause RangeError: Maximum call stack size exceeded

    constructor(
        api: ServiceFactory,
        identity: IdentityManager,
        options: RegisterOptions
    )
    {
        super(options);

        this.api = api;
        this.identity = identity;
    }
}

If we add DI parameter of 'IdentityManager', it cause

RangeError: Maximum call stack size exceeded
    at Function.keys (<anonymous>)
    at _traverse ... vue\dist\vue.runtime.common.dev.js:2117:19