【第4章 続き】

🟣 非同期 actionsawait 付きで安全に使うパターン

(Composition API × TypeScript × Vuex)


🎯 要点まとめ


🥕 たとえ:宅配ピザを注文する

Action = 「ピザください!」

→ 焼くのに30分かかる(非同期)。

→ 焼き上がるまで await して待つ。

→ 出てくるピザ(戻り値)の型もわかってる。


📦 型設計(戻り値まで型安全に)

store/types.ts

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

// mutation名
export const MutationTypes = {
  Increment: 'increment',
  SetUserName: 'setUserName'
} as const;

// action名
export const ActionTypes = {
  UpdateUserName: 'updateUserName'
} as const;

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

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

// actionの戻り値の型
export interface ActionReturns {
  [ActionTypes.UpdateUserName]: boolean; // 成功したらtrue
}


🟠 Store(index.ts

import Vue from 'vue';
import Vuex, { StoreOptions } from 'vuex';
import { RootState, MutationTypes, ActionTypes, MutationPayloads, ActionPayloads, ActionReturns } from './types';

Vue.use(Vuex);

export const store = new Vuex.Store<RootState>({
  state: {
    count: 0,
    userName: 'Taro'
  },
  mutations: {
    [MutationTypes.Increment](state) {
      state.count++;
    },
    [MutationTypes.SetUserName](state, name: string) {
      state.userName = name;
    }
  },
  actions: {
    // 戻り値に型をつける(Promise<boolean>)
    async [ActionTypes.UpdateUserName]({ commit }, name: ActionPayloads[typeof ActionTypes.UpdateUserName]): Promise<ActionReturns[typeof ActionTypes.UpdateUserName]> {
      await new Promise(resolve => setTimeout(resolve, 1000)); // 1秒待つ
      commit(MutationTypes.SetUserName, name);
      return true; // 成功を返す
    }
  }
});