Writing an event handler and discriminating on event type in typescript

Viewed 19

I'm trying to create an event handler that handles two types of events ("basic" and "complex" for the sake of the example), which in turn have two differently typed listeners (basic listeners take just a string, while complex listeners are more complex and take a number and a boolean). I type it as:

interface HandlerMap {
    "basic": (a: string) => void;
    "complex": (a: number, b: boolean) => void;
}

interface HandlerClass {
    on<E extends keyof HandlerMap>(type: E, listener:HandlerMap[E]): void;
}

and I want to use it like:

example.on("basic", (a: string) => { /* whatever implementation */ })
example.on("complex", (a: number, b: boolean) => { /* whatever implementation */ })

The problem is when I try to implement the class. I would expect this to work, but it doesn't discriminate the listener type correctly:

const example: HandlerClass = {
  on(type, listener) {
    if (type === "basic") {
      // this raises a type error!
      listener('example string')
    }
    if (type === "complex") {
      // this raises a type error!
      listener(77, true)
    }
  }
}

If I help it by casting, it works:

//...
    if (type === "basic") {
      (listener as HandlerMap["basic"])('example string')
    }
    if (type === "complex") {
      (listener as HandlerMap["complex"])(77, true)
    }

I expect automatic typing of the listener based on the type to be possible. What am I doing wrong?

0 Answers
Related