I am trying to strongly type a flux implementation (Vuex, to be more specific). My current code looks like this:
const actions = {
first(context: Context, payload: string) { return doSomething(context, payload); },
second(context: Context) { return doSomethingWithNoPayload(context); }
}
type Actions = typeof actions;
type PayloadType<A extends keyof Actions> = Parameters<Actions[A]>[1];
function dispatch<A extends keyof Actions>(action: A): ReturnType<Actions[A]>;
function dispatch<A extends keyof Actions>(action: A, payload: Payload<A>): ReturnType<Actions[A]>;
function dispatch<A extends keyof Actions>(action: A, payload: Payload<A> = undefined): Promise<any> {
return Promise.resolve({ action, payload });
}
What I am trying to accomplish is:
dispatch("first") // error, no payload specified
dispatch("first", false) // error, payload type is not correct
dispatch("first", "correct") // ok, payload type is correct
dispatch("second", "something") // error, shouldn't pass payload`
dispatch("second") // ok, payload is not passed
dispatch("third") // error, non-existent action
But using an optional parameter as the payload is not enforcing me to pass the payload to the "first" action that actually needs a payload. If I don't declare the payload as optional, then I'm forced to call dispatch("second", undefined) because now I need to pass 2 parameters.
Any thoughts? Much appreciated.