Dynamic modules

Vanilla, strongly-typed store accessor.

You can also use typed-vuex with dynamic modules.

Variable usage

Sample module

modules/dynamic-module.ts
export const namespaced = true

export const state = () => ({
  emails: [] as string[],
})

export const mutations = mutationTree(state, {
  addEmail(state, newEmail: string) {
    state.emails.push(newEmail)
  },
})

Accessing the module

You might want to use the store

components/my-component.vue
import Vue from 'vue

import { useAccessor, getAccessorType } from 'typed-vuex'
import * as dynamicModule from '~/modules/dynamic-module'

const accessorType = getAccessorType(dynamicModule)

export default Vue.extend({
  data: () => ({
    accessor: null as typeof accessorType | null,
  }),
  beforeCreated() {
    // make sure the namespaces match!
    this.$store.registerModule('dynamicModule', dynamicModule, {
      preserveState: false,
    })
    const accessor = useAccessor(this.$store, dynamicModule, 'dynamicModule')

    // this works and is typed
    accessor.addEmail('my@email.com')

    // but you might want to save the accessor for use elsewhere in your component
    this.accessor = accessor
  },
  methods: {
    anotherMethod() {
      // ... such as here
      if (this.accessor) {
        this.accessor.addEmail('my@email.com')
      }
    }
  }
})

Global usage

You can also register dynamic module on global level for your accessor. This can be a risky way, but can also be a way for large projects with no able of using useAccessor as variable.

Module definition

store/index.ts
import * as myImportedModule from '~/modules/myImportedModule'
import * as myNestedModule from '~/modules/myNestedModule'
import * as myDynamicModuleNoSpread from '~/modules/myImportedModuleNoSpread'

export const accessorType = getAccessorType({
  state,
  getters,
  mutations,
  actions,
  modules: {
    submodule: {
      //add this for module to show as possibly-undefined when using $accessor
      dynamic: true,
      namespaced: true,
      ...myImportedModule,
      modules: {
        myNestedModule,
      },
    },
    //You can add `export const dynamic = true;` inside module so you don't need to use spread operator in that case
    //View the example below
    submoduleWithoutSpread: myDynamicModuleNoSpread,
  },
})
modules/myImportedModuleNoSpread.ts
export const dynamic = true;

export const state = () => ({
  //...
});

Modules registration

components/my-component.vue
import Vue from 'vue

//Import from typed-vuex is not required in Nuxt
import { registerModule, unregisterModule } from 'typed-vuex'
import myImportedModule from '~/modules/myImportedModule'
import myNestedModule from '~/modules/myNestedModule'

export default Vue.extend({
  beforeCreated() {
    //Or this.$accessorRegisterModule('myImportedModule', myImportedModule) in Nuxt
    registerModule('myImportedModule', this.$store, this.$accessor, myImportedModule)

    //Or this.$accessorRegisterModule(['myImportedModule', 'myNestedModule'], myImportedModule) in Nuxt
    registerModule(['myImportedModule', 'myNestedModule'], this.$store, this.$accessor, myNestedModule)
    
    //You can also register two modules at once, but you MUST include namespaced: true in that case
    //this.$accessorRegisterModule('myImportedModule', {...}) syntax in Nuxt
    registerModule('myImportedModule', {
      ...myImportedModule,
      modules: {
        myNestedModule: {
          //required for correct usage, especially in Nuxt
          namespaced: true,
          ...myNestedModule,
        },
      },
    })
    
    //To unregister module(s), simply call this
    //this.$accessorUnregisterModule('myImportedModule') in Nuxt
    unregisterModule('myImportedModule', this.$store, this.$accessor)
  },
  methods: {
    anotherMethod() {
      //If you are not sure about if module will always exist, 
      // it is recommended to enable dynamic: true in store and always check for undefined
      if (this.accessor) {
        this.$accessor.myImportedModule?.myNestedModule?.addEmail('my@email.com')
      }
    }
  }
})

Typed $accessor methods

If you want methods $accessorRegisterModule and $accessorUnregisterModule to be typed, please add nuxt-typed-vuex package to tsconfig.json types.

tsconfig.json
{
  {
    "types": [
      "nuxt-typed-vuex"
    ]
  }
}