Vue3+Vuex4+TS中如何让mapActions映射的action获得正确类型
问题说明
搭配TypeScript使用Vue3 + Vuex4时,通过mapActions映射的方法默认会被推导为(...args: any[]) => Promise<any>类型,丢失原action定义的参数、返回值类型,以下是可落地的类型修复方案:
方案1:自定义类型安全的mapActions封装(适配Options API,无额外依赖)
Vuex4内置的mapActions类型未覆盖自定义action的参数推导,你可以基于自身store的action类型做一层轻量封装:
- 在store定义文件中提取action类型,重写mapActions的返回类型:
// src/store/index.ts import { createStore, Commit, mapActions as originalMapActions } from 'vuex' // 定义你的state类型 export interface MyStoreState { // 补充自身state字段定义 } // 直接定义actions对象,不要写在createStore配置里,方便提取类型 const actions = { async anAction( { commit, state }: { commit: Commit; state: MyStoreState }, payload: { parameter1: string; parameter2: number } ) { // 业务逻辑 commit('xxx', /* 相关参数 */) }, // 其余action统一写在这里 } // 提取action的对外调用类型(去掉第一个context参数,保留payload和返回值) type ActionsType = typeof actions type MappedActions = { [K in keyof ActionsType]: ActionsType[K] extends (ctx: unknown, ...args: infer P) => infer R ? (...args: P) => R : never } // 导出类型化的mapActions export const typedMapActions = <T extends keyof MappedActions>(actionKeys: T[]) => { return originalMapActions(actionKeys) as { [Key in T]: MappedActions[Key] } } // 正常创建store实例 export default createStore<MyStoreState>({ state: {}, mutations: {}, actions, })
- 组件中替换原
mapActions为自定义的typedMapActions即可获得完整类型校验:
import { typedMapActions } from '@/store' export default { methods: { ...typedMapActions(['anAction']) }, mounted() { // 此处调用this.anAction会自动提示payload结构,参数类型错误会直接抛出TS报错 this.anAction({ parameter1: 'demo', parameter2: 1 }) } }
方案2:使用组合式API+类型化useStore(Vuex4官方推荐写法)
如果可以接受组合式API写法,不需要依赖map辅助函数,直接给useStore加上类型即可获得完整的dispatch类型推导:
- 在store文件中导出类型化的useStore钩子:
import { useStore as baseUseStore, Store } from 'vuex' // 补充store的dispatch类型重载 export type TypedStore = Store<MyStoreState> & { dispatch: { <K extends keyof ActionsType>( type: K, ...args: ActionsType[K] extends (ctx: unknown, ...payload: infer P) => unknown ? P : [] ): ReturnType<ActionsType[K]> } } export const useStore = () => baseUseStore() as TypedStore
- 组件中直接调用即可获得类型提示:
import { useStore } from '@/store' export default { setup() { const store = useStore() const triggerAction = () => { // dispatch会自动校验action名、payload参数类型 store.dispatch('anAction', { parameter1: 'demo', parameter2: 1 }) } return { triggerAction } } }
方案3:使用Vuex类型辅助工具
如果不想手动维护类型封装,可以引入专门的Vuex TS类型增强工具,按照工具要求定义store模块类型后,即可获得带完整类型推导的mapActions、mapMutations等映射方法。
Vuex4没有内置map辅助函数的完美类型推导,核心原因是mapActions支持命名空间、对象格式映射、多模块等多种灵活用法,内置泛型很难覆盖所有场景,手动封装类型是目前最灵活、适配性最高的方案。
内容的提问来源于stack exchange,提问作者Samuele B.
相关产品推荐
相关产品推荐

