Created
January 8, 2019 12:50
-
-
Save romansp/72e0019e0e02b27da92b378922b67940 to your computer and use it in GitHub Desktop.
Type-safe vuex payloads
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Payload } from "vuex"; | |
import { PayloadMap, ActionTree } from "./vuex-typed"; | |
import { State } from "./state"; | |
import { Mutation } from "./mutations"; | |
// define action types by adding new values to this enum | |
export enum ActionTypes { | |
Action = "Action", | |
} | |
// add mutation payload class | |
export class Action implements Payload { | |
public readonly type = ActionTypes.Action; | |
constructor(public readonly actionPayload: string) { } | |
} | |
// defining a map between action key and action payload | |
// PayloadMap enforces action `type` field value and key value to be equal | |
// otherwise it will throw compile-time error | |
export interface ActionPayloadMap extends PayloadMap<ActionTypes> { | |
[ActionTypes.Action]: Action; | |
} | |
const actions: ActionTree<State, State, ActionPayloadMap> = { | |
// action payload type is inferred from action type | |
async [ActionTypes.Action]({ commit }, { actionPayload }) { | |
commit(new Mutation(actionPayload)) | |
}, | |
} | |
export default actions; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import store from "./store"; | |
import { Action } from "./store/actions"; | |
import { Mutation } from "./store/mutations"; | |
// when dispatching actions and commiting mutations payload is typed | |
store.dispatch(new Action("hello")); | |
store.commit(new Mutation("hello")); | |
// compilation error: Argument of type '1' is not assignable to parameter of type 'string' | |
store.commit(new Mutation(1)); | |
// compilation error: Expected 1 arguments, but got 0. | |
store.commit(new Mutation()); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Payload } from "vuex"; | |
import { PayloadMap, MutationTree } from "./vuex-typed"; | |
import { State } from "./state"; | |
// define mutation types by adding new values to this enum | |
export enum MutationTypes { | |
Mutation = "Mutation", | |
} | |
// add mutation payload classes | |
export class Mutation implements Payload { | |
public readonly type = MutationTypes.Mutation; | |
constructor(public readonly mutationPayload: string) { } | |
} | |
// defining a map between mutation key and mutaion payload | |
// PayloadMap enforces mutation `type` field value and key value to be equal | |
// otherwise it will throw compile-time error | |
export interface MutationPayloadMap extends PayloadMap<MutationTypes> { | |
[MutationTypes.Mutation]: Mutation; | |
} | |
const mutations: MutationTree<State, MutationPayloadMap> = { | |
// mutation payload type is inferred from mutation type | |
async [MutationTypes.Mutation](state, { mutationPayload }) { | |
state.value = mutationPayload; | |
}, | |
} | |
export default mutations; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export interface State { | |
value: string; | |
} | |
const state: State = { | |
value: "" | |
}; | |
export default state; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Vuex from "vuex"; | |
import actions from "./actions"; | |
import mutations from "./mutations"; | |
import state from "./state"; | |
export default new Vuex.Store({ | |
state, | |
actions, | |
mutations, | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ActionContext } from "vuex"; | |
type ActionHandler<S, R, P> = (injectee: ActionContext<S, R>, payload: P) => any; | |
interface ActionObject<S, R, P> { | |
root?: boolean; | |
handler: ActionHandler<S, R, P>; | |
} | |
type Mutation<S, P = any> = ((state: S, payload: P) => any); | |
type Action<S, R, P> = ActionHandler<S, R, P> | ActionObject<S, R, P>; | |
export type MutationTree<S, M = any> = { [P in keyof M]: Mutation<S, M[P]> }; | |
export type ActionTree<S, R, M = any> = { [P in keyof M]: Action<S, R, M[P]> }; | |
export interface Payload<T = string> { | |
readonly type: T; | |
} | |
export type PayloadMap<T extends keyof any> = { [P in T]: Payload<P> }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment