Trying to explain this may be a bit challenging. The example provided is intricate, but efforts have been made to simplify it while retaining the error.
type Handler = (...args: any[]) => void;
const handlers: { [eventName: string]: Handler } = {};
type Events = {
// Map event signature (arg types) to event name
[eventName: string]: any[];
};
function createOnEvent<UserEvents extends Events>() {
type ValidEventName = Extract<keyof UserEvents, string>;
return <EventName extends ValidEventName>(
eventName: EventName,
eventHandler: (...args: UserEvents[EventName]) => void,
) => {
handlers[eventName] = eventHandler; // [0] ERROR HERE
};
}
[0] Type 'any[]' is not assignable to type 'UserEvents[EventName]'
There are two points of confusion:
UserEvents[EventName]
should matchany[]
- The attempt is to assign
UserEvents[EventName]
toany[]
, not vice versa...
Here is how this API can be utilized:
type FooEvents = {
eventOne: [number];
eventTwo: [string, boolean];
};
const onEvent = createOnEvent<FooEvents>();
onEvent('eventOne', (arg1: number) => null); // OK
onEvent('eventTwo', (arg1: string, arg2: boolean) => null); // OK
onEvent('eventOne', (arg1: string) => null); // error
Everything seems to work fine except for storing the handler in handlers
, which should accept functions with any argument list.
This situation may seem perplexing, so feel free to ask for clarification if needed. It would be great to resolve this issue. Thank you!