Vuex4 typescript 中自动将modules的类型添加到state中

2,014 阅读1分钟

在vuex4中使用typescript的时候,用模块modules时,如果不做一些处理,用Hooks获取store然后取子模块的state会丢失类型。

首先需要参照vuex4.0中使用typescript, vuex4.0中modules的ts使用,vue3 + vuex4.0 + typescript 使用详情来设置一些基础的东西,但是原文中美中不足的就是需要自己添加module state类型上去,接下来把这一步也处理一下让TypeScript自己去获取。

直接上代码吧

import { InjectionKey } from 'vue'
import { createStore, Store, useStore as baseUseStore, } from 'vuex'
import UserinfoStore from './user.store'

// 为 store state 声明类型
export interface State extends modulesState{}

type modulesState = {
  [key in keyof typeof modules]: Exclude<Exclude<typeof modules[key]['state'], undefined>, () => any>
}
// 定义 injection key
export const key: InjectionKey<Store<State>> = Symbol()

const modules = {
  UserinfoStore,
}
export const store = createStore<State>({
  modules,
})
// 定义自己的 `useStore` 组合式函数
export function useStore () {
  return baseUseStore<State>(key)
}

最关键的一句代码就是[key in keyof typeof modules]: Exclude<Exclude<typeof modules[key]['state'], undefined>, () => any>

直接获取typeof modules[key]['state']会有问题,因为Module类型中的State被官方指定为了联合类型,直接用的话,根本点不出来任何东西,需要做进一步的处理。

export interface Module<S, R> {
  namespaced?: boolean;
  state?: S | (() => S);
  getters?: GetterTree<S, R>;
  actions?: ActionTree<S, R>;
  mutations?: MutationTree<S>;
  modules?: ModuleTree<R>;
}

其中state?: S | (() => S);转化出来就是S | (() => S) | undefined, 我们这里只需要获取泛型S的类型就可以了,那么就可以用到高级类型Exclude去把不需要的类型剔除出去,首先剔除 undefined,然后剔除函数类型() => S拿不到S就用any大法替代,就这样,成功的获取到了Modules的State类型。

image.png