前言
前几天,TypeScript 发布了一项 4.1 版本的新特性,字符串模板类型,还没有了解过的小伙伴可以先去这篇看一下:TypeScript 4.1 新特性:字符串模板类型,Vuex 终于有救了?。
本文就利用这个特性,简单实现下 Vuex 在 modules
嵌套情况下的 dispatch
字符串类型推断,先看下效果,我们有这样结构的 store
:
const store = Vuex({
mutations: {
root() {
},
},
modules: {
cart: {
mutations: {
add() {
},
remove() {
},
},
},
user: {
mutations: {
login() {
},
},
modules: {
admin: {
mutations: {
login() {
},
},
},
},
},
},
})
需要实现这样的效果,在 dispatch
的时候可选的 action
字符串类型要可以被提示出来:
store.dispatch('root')
store.dispatch('cart/add')
store.dispatch('user/login')
store.dispatch('user/admin/login')
实现
定义函数骨架
首先先定义好 Vuex 这个函数,用两个泛型把 mutations
和 modules
通过反向推导给拿到:
type Store<Mutations, Modules> = {
// 下文会实现这个 Action 类型
dispatch(action: Action<Mutations, Modules>): void
}
type VuexOptions<Mutations, Modules> = {
mutations: Mutations
modules: Modules
}
declare function Vuex<Mutations, Modules>(
options: VuexOptions<Mutations, Modules>
): Store<Mutations, Modules>
实现 Action
那么接下来的重点就是实现 dispatch(action: Action): void
中的 Action
了,我们的目标是把他推断成一个 'root' | 'cart/add' | 'user/login' | 'user/admin/login'
这样的联合类型,这样用户在调用 dispatch
的时候,就可以智能提示了。
Action
里首先可以简单的先把 keyof Mutations
拿到,因为根 store
下的 mutations
不需要做任何的拼接,
重头戏在于,我们需要根据 Modules
这个泛型,也就是对应结构:
modules: {
cart: {
mutations: