4

Let's say I have a function:

function registerEvent(event: Event, handler: HandlerSignature);

and these are the respective types:

enum Event {
  EventOne,
  EventTwo
}

type HandlerSignature = (...args: any[]) => void;

Now every event could have a different function signature, for example:

function handler1(foo: number, bar: string);
function handler2(foo: string);

What I'd like to achieve is that I can call the registerEvent function, specify the first arg (event) and let TypeScript detect which signature corresponds with this event, i.e. for intellisense and to prevent users from assigning wrong signatures to an event.

I thought about creating a map where I assign the different signatures to the enum values, but I can't really use that as type, can I? Even if I used a mapped type I'd have to create a variable to assign all the events.

1 Answer 1

7

I'd lean toward function overloading:

enum Events {
  EventOne,
  EventTwo
}

type HandlerSignature = (...args: any[]) => void;

function registerEvent(event: Events.EventOne, handler: (foo: number, bar: string) => void): void;
function registerEvent(event: Events.EventTwo, handler: (foo: number) => void): void;
function registerEvent(event: Events, handler: HandlerSignature):void {
    // ...implementation
}

function handler1(foo: number, bar: string) {}
function handler2(foo: string) {}

registerEvent(Events.EventOne, handler1); // Works
registerEvent(Events.EventOne, handler2); // Error as desired, wrong type for callback

Playground link

(Note I changed Event to Events; Event is a pre-existing global and type in the browser environment and Node.js)

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you so much! This is a very elegant approach, I didn't even know that overloading works like this.
@Blade - My pleasure. I should note that it only works this way when the event is a constant value. If you had a variable of type Events, then of course TypeScript doesn't know what specific value it will have at runtime so it'll expect a handler that can handle either call.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.