Currently, I am working on implementing strong typing for a flux framework (specifically Vuex). Here is my current code:
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 });
}
The goal of this implementation is to achieve the following behavior:
dispatch("first") // error, payload not specified
dispatch("first", false) // error, incorrect payload type
dispatch("first", "correct") // correct, valid payload type
dispatch("second", "something") // error, should not accept payload
dispatch("second") // correct, no payload needed
dispatch("third") // error, non-existent action
Using an optional parameter for the payload is causing issues because it does not enforce passing the payload to the "first" action which requires one. On the other hand, if the payload is not declared as optional, then calling dispatch("second", undefined)
becomes necessary due to needing to pass two parameters.
Any suggestions or thoughts on how to tackle this issue would be greatly appreciated.