Vuex4 (4) modules + typeScript

vuex4.xx 버전 저장소들을 모듈화시킬때 타입스크립트를 적용하는 방법 정리
해당 연습 깃허브 커밋
폴더 구조

공통

store/board/board.type.ts

export interface boardType {
    boardData: boardDesc[];
}

export interface boardDesc {
    index: number;
    tit: string;
    desc: string;
}

store/autho/autho.type.ts

export interface userInfoType {
    index: number;
    userName: string;
    userId: string;
}

store/index.ts

모듈을 import 하고 rootState 를 선언해줘야한다.

import { createStore } from "vuex";
import { userInfoType } from "./autho/autho.type"
import { boardType } from './board/board.type';
import { ModuleUserInfo } from './autho'
import { ModuleBoard } from './board/index'

export interface RootState {
  ModuleUserInfo: userInfoType;
  ModuleBoard: boardType;
}

export default createStore({
  modules: {
    ModuleUserInfo, ModuleBoard
  },
});

구성요소 분리 X

기존에 js 스타일과 큰 차이는 없다 타입스크립트의 타입 정의하는 문법과 vuex 의 module 이라는 내장함수에 맞게 형식 변환하고 localState, rootState 를 선언하는 것이 필요함

import { Module } from "vuex";
import { RootState } from "../index";
import { boardType, boardDesc } from './board.type'


export const ModuleBoard: Module<boardType, RootState> = {
    state: {
        boardData: [
            {
                tit: 'title',
                desc: 'board desc'
            }
        ]
    },
    mutations: {
        BOARD_UPDATE(state: boardType, payload: boardDesc) {
            state.boardData.push(payload)
        }
    },
    actions: {
        boardUpdate({ state, commit, rootState }, payload) {
            console.log(state, rootState)
            commit('BOARD_UPDATE', payload)
        }
    },
    getters: {
        boardList: (state, rootGetter, rootState) => {
            console.log(rootGetter)
            console.log(rootState)
            return state.boardData
        }
    }

}

구성요소 분리 O

프로젝트가 커질수록 구성요소가 많아지는 경우가 있다. 각 구성요소별로 관리하기 쉽게 나눠줄 수 있다.

store/autho/index.ts

각 구성요소를 import 하는 것 외엔 구성요소가 분리 되지 않는 작성법과 동일하다

import { Module } from "vuex";
import { state } from "./state";
import { mutations } from "./mutation";
import { actions } from "./actions";
import { getters } from "./getters";
import { userInfoType } from "./autho.type"
import { RootState } from "../index";

export const ModuleUserInfo: Module<userInfoType, RootState> = {
    state,
    getters,
    actions,
    mutations
};

store/autho/state.ts

type 파일 import 하는 것은 생략해도 index.ts 에서 선언 되어 있어서 누락되거나 잘못될경우 에러메세지를 낸다.

import { userInfoType } from "./autho.type"

export const state = {
    index: 1,
    userName: "",
    userId: "userID",
} as userInfoType;

store/autho/getters.ts

getters 를 사용하기 위한 타입을 선언해주고 내장 함수 GetterTree를 사용 타입을 지정해준다. *GetterTree 함수에 대한 공식 문서를 찾지 못함...

import { GetterTree } from "vuex";
import { RootState } from "@/store";
import { userInfoType } from "./autho.type";

export type Getters = {
    userIdGetters(state: userInfoType, getters: RootState, rootState: RootState): string;
};

export const getters: GetterTree<userInfoType, RootState> & Getters = {
    userIdGetters: (state: userInfoType, getters: RootState, rootState: RootState) => {
        console.log('login_getter', getters, rootState)
        return state.userId
    },
};

store/autho/mutation.type.ts

mutation 과 actions는 아래처럼 각 타입을 선언한다.
GetterTree 와 유사하게 MutationTree를 사용한다.

export enum MutationType {
    LOGIN = "LOGIN"
}

store/autho/mutation.ts

import { MutationTree } from "vuex";
import { userInfoType } from "./autho.type";
import { MutationType } from "./mutation.type";

export type Mutations<S = userInfoType> = {
    [MutationType.LOGIN](state: S, payload: userInfoType): void;
};

export const mutations: MutationTree<userInfoType> & Mutations = {
    [MutationType.LOGIN](state: userInfoType, payload: userInfoType) {
        state.userId = payload.userId
        state.userName = payload.userName
    },
};

store/autho/action.type.ts

action 에선 mutations 를 호출해서 사용해야하기 때문에 mutation.type 과 mutation 도 import 해야한다.
AugmentedActionContext 은 context 에 대한 타입을 선언해주는 부분.

export enum ActionType {
    login = "login",
}

store/autho/action.ts

import { ActionTree, ActionContext } from "vuex";
import { RootState } from "@/store";
import { Mutations } from "./mutation";
import { MutationType } from "./mutation.type";
import { userInfoType } from "./autho.type";
import { ActionType } from "./actions.type";

type AugmentedActionContext = {
    commit<K extends keyof Mutations>(
        key: K,
        payload: Parameters<Mutations[K]>[1]
    ): ReturnType<Mutations[K]>;
} & Omit<ActionContext<userInfoType, RootState>, "commit">;

export interface Actions {
    [ActionType.login](
        { commit }: AugmentedActionContext,
        payload: userInfoType
    ): void;

}

export const actions: ActionTree<userInfoType, RootState> & Actions = {
    [ActionType.login]({ commit, state, rootState }, payload) {
        console.log('login_action', state, rootState);
        commit(MutationType.LOGIN, payload);
    },
};

좋은 웹페이지 즐겨찾기