「mutation / action の名前(type)」と「payload(引数)」をセットで型で管理する
「この mutation にはこの payload!」と決めておくことで
間違った型を渡したらその場でエラーになる
TypeScript の キーと型の組み合わせ (Mapped Types
) を活用
commitTyped
, dispatchTyped
を使う
「3番のピザ」には「枚数」を書く必要がある。
「4番のパスタ」には「ソースの種類」が必要。
メニュー番号と内容がバラバラだったら怒られる。
それが 型安全なpayload設計。
types.ts
)// RootState
export interface RootState {
count: number;
userName: string;
}
// mutation名
export const MutationTypes = {
Increment: 'increment',
SetUserName: 'setUserName'
} as const;
export type MutationType = typeof MutationTypes[keyof typeof MutationTypes];
// action名
export const ActionTypes = {
UpdateUserName: 'updateUserName'
} as const;
export type ActionType = typeof ActionTypes[keyof typeof ActionTypes];
// mutation payloads(引数の型)
export interface MutationPayloads {
[MutationTypes.Increment]: undefined; // incrementは引数なし
[MutationTypes.SetUserName]: string; // setUserNameはstring型
}
// action payloads(引数の型)
export interface ActionPayloads {
[ActionTypes.UpdateUserName]: string; // updateUserNameはstring型
}
// action returns(戻り値の型)
export interface ActionReturns {
[ActionTypes.UpdateUserName]: boolean; // 戻り値はboolean
}
commitTyped
実装import { Store } from 'vuex';
import { RootState, MutationType, MutationPayloads } from './types';
// 型付きcommit
export const commitTyped = <
T extends MutationType
>(
store: Store<RootState>,
type: T,
payload: MutationPayloads[T]
): void => {
store.commit(type, payload);
};
✅ ここで MutationPayloads[T]
によって
increment
には undefined
しか渡せない