使用Typescript给vuex添加类型声明

1,878 阅读2分钟

vuex@4与Typescript

简单分享一个使用Typescript给vuex的加上类型检测的技巧。只能对state有进行类型声明.

其他优秀解决方案,文末附跳转链接.

正文

简单搭建store结构

store/index.ts 根state

import { createStore } from 'vuex';
// 导入子模块
import home from './home/home';
import login from './login/login';
// 导入根模块类型
import type { IRootState } from './types';
​
// 在调用createStore是传入一个自己root的type
const store = createStore<IRootState>({
  state: () => {
    return {
      name: 'red',
      age: 20
    };
  },
  getters: {},
  mutations: {},
  actions: {}
});
​
export default store;

store/home/home.ts 子模块home

import { Module } from 'vuex';
// 导入home的state类型
import type { IHomeState } from './home-types';
import type { IRootState } from '../types';
// 借助vuex中的 Module接口 给子模块传入本模块与父模块的state的类型.
// 第一个传本模块的类型,第二个传父模块的类型
const home: Module<IHomeState, IRootState> = {
  namespaced: true,
  state() {
    return {
      invitationProgress: 3
    };
  },
  getters: {},
  mutations: {},
  actions: {}
};
​
export default home;

store/login.ts 子模块login

// 结构与home无异
import { Module } from 'vuex';
import type { ILoginState } from './login-types';
import type { IRootState } from '../types';
​
const login: Module<ILoginState, IRootState> = {
  namespaced: true,
  state() {
    return {
      login: 'hello we are login module'
    };
  },
  getters: {},
  mutations: {},
  actions: {}
};
​
export default login;

主角 关键

store/types.ts

// 导入子模块home的类型
import { IHomeState } from './home/home-types';
import { ILoginState } from './login/login-types';
// root模块的类型
export interface IRootState {
  name: string;
  age: number;
}
// 写一个所有子模块类型的接口
export interface IModuleState {
  home: IHomeState;
  login: ILoginState;
}
// 将根模块与子模块接口合并导出
export type IStore = IRootState & IModuleState;

回到store/index.ts

// 1.在这里导入useStore,为了区别自己导出的useStore给他取一个别名为useVuexStore(随意)
import { createStore, Store, useStore as useVuexStore } from 'vuex';
​
import home from './home/home';
import login from './login/login';
import type { IRootState } from './types';
// 2.导入整个store的类型
import type { IStore } from './types';
​
const store = createStore<IRootState>({
    ...
})
    
export default store;
// 2.自己写一个useStore并导出. 函数返回值是Store,Store的类型的是自己编写的IStore.
export function useStore(): Store<IStore> {
    // 执行从vuex导入useStore并return出去
  return useVuexStore();
}

简单测试

// 从此不再使用vuex里面的useStore
// import { useStore } from 'vuex';// 从自己的store/index.ts 导出store使用
import { useStore } from '@/store';
​
const store = useStore();
console.log(store.state.name);

1642044631667.png

1642044667511.png

1642044681441.png

成功提示

来自coderwhy

==

其他方案链接

vuex@4官方文档的方式

TypeScript 支持 | Vuex (vuejs.org)

使用Pinia

Pinia (vuejs.org)

  • vue核心团队成员 posva (Eduardo San Martin Morote) 开发
  • 与vuex的API几乎一样, 易上手.
  • 支持 Vue.js devtools , 为您提供增强的Vue2和Vue3开发体验。
  • 无需像 Vuex@4自定义复杂的类型来支持 typescript,天生具备完美的类型推断。
  • Pinia 大小约1kb