Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make EventListener covariant #35211

Closed
wants to merge 1 commit into from

Conversation

creeefs
Copy link

@creeefs creeefs commented Nov 19, 2019

Fixes #28357

Currently, the EventListener interface is invariant. As a result, functions that pass a subtype of Event fail to compile (e.g. see the CustomEvent and MessageEvent examples below).

CustomEvent handler

obj.addEventListener("customEvt", (e: CustomEvent) => {});
Type '(e: CustomEvent<any>) => void' is not assignable to type 'EventListener'.
    Types of parameters 'e' and 'evt' are incompatible.
        Type 'Event' is missing the following properties from type 'CustomEvent<any>': detail, initCustomEvent  TS2345

MessageEvent handler

eventSource.addEventListener("messageEvt", (e: MessageEvent) => {});
Type '(e: MessageEvent) => void' is not assignable to type 'EventListener'.
    Types of parameters 'e' and 'evt' are incompatible.
        Type 'Event' is missing the following properties from type 'MessageEvent': data, lastEventId, origin, ports, source  TS2345

As a result, it seems like a lot of people resort to using the as EventListener type assertion.

evtSource.addEventListener("messageEvt", ((e: MessageEvent) => {}) as EventListener);

Instead of having users resort to the as operator, I'm proposing we introduce a generic type variable that extends Event to the EventListener interface. We could then pass the appropriate sub-type to the addEventHandler functions for the respective objects (e.g. EventSource below).

interface EventSource extends EventTarget {
    addEventListener(type: string, listener: EventListenerOrEventListenerObject<MessageEvent>, options?: boolean | AddEventListenerOptions): void;
}

The net result would be to allow users to simply do:

evtSource.addEventListener("messageEvt", (e: MessageEvent) => {});

11/19/19: Note that the PR currently only implements the changes for the EventSource interface. I'd like to get some feedback before porting the change to every other object.

@typescript-bot
Copy link
Collaborator

It looks like you've sent a pull request to update our 'lib' files. These files aren't meant to be edited by hand, as they consist of last-known good states of the compiler and are generated from 'src'. Unless this is necessary, consider closing the pull request and sending a separate PR to update 'src'.

@typescript-bot
Copy link
Collaborator

It looks like you've sent a pull request to update some generated declaration files related to the DOM. These files aren't meant to be edited by hand, as they are synchronized with files in the TSJS-lib-generator repository. You can read more here. For house-keeping purposes, this pull request will be closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lib update PR modifies files in the `lib` folder
Projects
None yet
Development

Successfully merging this pull request may close these issues.

TypeScript doesn't allow event : CustomEvent in addEventListener
2 participants