I want to have a function that returns a new function whose type is dependent on the parameters passed in to the wrapping function. The wrapping function should take as parameters a function and an object. Here is some of the type info:
type Event = {};
type EventExecutor<T extends Event> = (event: T) => void;
type EventMap<T extends Event> = {
[id: string]: (...args: any) => T;
};
and the function would be implemented something like:
function createEventHandler<
T extends Event,
M extends EventMap<T>,
K extends keyof M
>(executor: EventExecutor<T>, eventMap: M) {
return (id: K, ...params: Parameters<M[K]>) => {
const event = eventMap[id](...params);
executor(event);
};
}
The way I expect it to work is:
type MyEventA = { type: 'foo', fizz: string };
type MyEventB = { type: 'bar', buzz: number };
type MyEvent = MyEventA | MyEventB;
function myEventExecutor(event: MyEvent) {
// ...
}
const myEventMap = {
hello: (p: string) => ({ type: 'foo', fizz: p }),
goodbye: (n: number) => ({ type: 'bar', buzz: n }),
};
const myHandler = createEventHandler(myEventExecutor, myEventMap);
myHandler('hello', 'world'); // correct
myHandler('goodbye', 42); // correct
myHandler('hello', 42); // ERROR
myHandler('goodbye', 'world'); // ERROR
myHandler('wrong', 'stuff'); // ERROR
There's some issues with what I currently have. One it seems like I lose all the type info for id in myHandler...any string passes without an error. Same goes for the parameters as well.
I'm really not sure what the issue is tbh since the type info seems like it makes sense???
Additionally, I would like to be able to have the event map be either the function that returns the generic Event OR just that generic Event (in other words a static event)... Event | (...args: any) => Event ... but I'm fine if I'm not able to do that.