【第5章】型付き commit, dispatch を作る(Vuex × TypeScript 完全型安全設計)


🎯 要点まとめ


🥕 たとえ:注文票に「メニュー番号と個数」両方必要

「3番のラーメン2つください!」

→ メニュー番号間違ってたら店員に怒られる。

→ 個数を間違っても怒られる。

番号と内容がセットで正しいかどうかチェック

それが型付き commit / dispatch


📦 基本設計(types.ts

// RootState
export interface RootState {
  count: number;
  userName: string;
}

// Mutation types
export const MutationTypes = {
  Increment: 'increment',
  SetUserName: 'setUserName'
} as const;
export type MutationType = typeof MutationTypes[keyof typeof MutationTypes];

// Action types
export const ActionTypes = {
  UpdateUserName: 'updateUserName'
} as const;
export type ActionType = typeof ActionTypes[keyof typeof ActionTypes];

// mutation payloads
export interface MutationPayloads {
  [MutationTypes.Increment]: undefined;
  [MutationTypes.SetUserName]: string;
}

// action payloads
export interface ActionPayloads {
  [ActionTypes.UpdateUserName]: string;
}

// action returns
export interface ActionReturns {
  [ActionTypes.UpdateUserName]: boolean;
}


🟠 commitTyped の作成

// 型付き commit 関数
import { Store } from 'vuex';
import { RootState, MutationType, MutationPayloads } from './types';

export const commitTyped = <
  T extends MutationType
>(
  store: Store<RootState>,
  type: T,
  payload: MutationPayloads[T]
): void => {
  store.commit(type, payload);
};


🟣 dispatchTyped の作成

// 型付き dispatch 関数
import { ActionType, ActionPayloads, ActionReturns } from './types';

export const dispatchTyped = async <
  T extends ActionType
>(
  store: Store<RootState>,
  type: T,
  payload: ActionPayloads[T]
): Promise<ActionReturns[T]> => {
  return await store.dispatch(type, payload);
};