Vuex4适配Vue3:如何实现通用ActionAugment泛型类型
实现Vuex4通用ActionAugment泛型类型方案
我来帮你搞定这个通用ActionAugment类型的问题!核心就是把硬编码的AppMutation和AppMutationType替换成泛型参数,让这个类型能在任意Vuex模块里复用。
步骤1:改造globalStore.ts里的ActionAugment类型
我们需要让ActionAugment接收三个泛型参数:
S: 当前模块的State类型M: 当前模块的Mutation对象类型MT: 当前模块的Mutation枚举类型(可选,默认用keyof M)
修改后的代码如下:
import { ActionContext } from 'vuex'; // globalStore.ts type State = { app: AppState; } // 通用泛型ActionAugment,支持任意模块的Mutation和MutationTypes type ActionAugment<S, M, MT extends keyof M = keyof M> = Omit<ActionContext<S, State>, 'commit'> & { commit<K extends MT>( key: K, payload: Parameters<M[K]>[1] ): ReturnType<M[K]>; }; // end globalStore.ts
这里的关键改动:
- 用泛型
M替代了硬编码的AppMutation,用MT替代了AppMutationType - 给
commit方法加了泛型约束K extends MT,确保只能传入当前模块的Mutation类型键 Parameters<M[K]>[1]自动提取对应Mutation方法的第二个参数(第一个是state)作为payload类型ReturnType<M[K]>自动匹配Mutation方法的返回类型
步骤2:在appStore.ts中复用这个类型
现在你可以直接把模块的AppMutation和AppMutationType传给ActionAugment,不用再硬编码:
// appStore.ts type AppState = { isLoaded: boolean; }; enum AppMutationType { Mutation = 'MUTATION', } enum AppActionType { Action = 'ACTION', } type AppMutation = { [AppMutationType.Mutation](state: AppState, isLoaded: boolean): void; }; const actions = { [AppActionType.Action]({ commit }: ActionAugment<AppState, AppMutation, AppMutationType>, isLoaded: boolean) { // 这里commit会自动提示AppMutationType的枚举值,payload类型也会被正确校验 commit(AppMutationType.Mutation, isLoaded); }, }; // end appStore.ts
额外福利:无枚举场景的复用
如果你的模块没有用枚举定义Mutation类型,直接用字符串键也能生效,因为我们给MT设置了默认值keyof M:
// 示例:没有枚举的模块 type UserState = { name: string; }; type UserMutation = { SET_NAME(state: UserState, name: string): void; }; const userActions = { setUserName({ commit }: ActionAugment<UserState, UserMutation>, name: string) { // 这里commit会自动提示'SET_NAME',payload类型为string commit('SET_NAME', name); }, };
这下每个模块都能轻松复用这个通用的ActionAugment类型,不用再重复写类似的类型定义啦!
内容的提问来源于stack exchange,提问作者German Casares
相关产品推荐
相关产品推荐

