Vue官方改用Pinia替代Vuex提供TypeScript支持,原Vuex多模块静态类型智能提示异常问题求助
重要编辑提示:自2021年底多伦多Vue大会后,Vue官方已正式改用Pinia替代Vuex以提供TypeScript支持。官方同时承认,在使用TypeScript并将Store拆分为多个模块时,Vuex的使用难度极高,难以保留TypeScript的大部分优势。因此原问题已不再具有相关性,推荐使用Pinia来实现类型安全的状态管理。
Hey there! Let's break down what's happening here and how to fix that frustrating intellisense issue you're facing.
问题根源
当你用&交叉两个都包含commit和dispatch方法(各自带泛型重载)的Store类型时,TypeScript很难正确合并这些函数签名。它不会把两个模块的所有mutation和action都整合起来,反而会优先识别交叉类型中最后一个模块的签名——这就是为什么只有最后那个模块的commit/dispatch能正常触发智能提示。而getters能正常工作,是因为它们是对象类型,TypeScript在交叉类型时会自动合并所有属性。
解决方案
不要直接交叉两个模块的Store类型,我们来构建一个根Store类型,显式合并两个模块的commit、dispatch和getters:
首先,定义合并后的commit、dispatch和getters类型:
// 导入你的模块Store类型 import type { DocumentationStore, WorkAgreementStore } from './modules'; import type { RootState } from './index'; import type { Store } from 'vuex'; // 合并两个模块的commit签名 type RootCommit = DocumentationStore['commit'] & WorkAgreementStore['commit']; // 合并两个模块的dispatch签名 type RootDispatch = DocumentationStore['dispatch'] & WorkAgreementStore['dispatch']; // 合并所有getters type RootGetters = DocumentationStore['getters'] & WorkAgreementStore['getters']; // 创建根Store类型,用我们合并后的类型替换默认的commit/dispatch/getters type RootStore = Omit<Store<RootState>, 'commit' | 'dispatch' | 'getters'> & { commit: RootCommit; dispatch: RootDispatch; getters: RootGetters; };
然后更新你的useStore函数,返回这个新的根类型:
export function useStore(): RootStore { return store as RootStore; }
这样TypeScript就能正确识别两个模块的所有mutation和action,commit/dispatch的智能提示就能正常工作了。
额外检查
另外,你可以再确认一下模块级的Store类型(比如WorkAgreementStore)是否正确引用了RootState。有时候状态类型的不匹配也会导致一些微妙的智能提示问题。
内容的提问来源于stack exchange,提问作者SleepDeprivedMango

