-
Notifications
You must be signed in to change notification settings - Fork 13k
Description
🔎 Search Terms
onerror GlobalEventHandlers
🕗 Version & Regression Information
As far as I can tell, this has always been wrong. There are a number of issues (and merged fixes) around onerror
and/or addEventListener("error"
, but all of them have concerned themselves with getting the definition correct for Window
.
⏯ Playground Link
💻 Code
declare const htmlElement: HTMLElement;
htmlElement.onerror((event: Event) => {}); // should not error
🙁 Actual behavior
The type definitions in lib.dom.d.ts
for addEventListener("error"
and onerror
used by HTMLElement
match the spec for Window
, which has unique handling of these events for historical reasons.
🙂 Expected behavior
The type definitions in lib.dom.d.ts
for addEventListener("error"
and onerror
event handling on HTMLElement
would match the spec for HTMLElement
.
Additional information about the issue
In lib.dom.d.ts
, we have GlobalEventHandlersEventMap
, which is used to define addEventListener
, and GlobalEventHandlers
, used to define the various on${string}
event handler properties. As the name suggests, these are meant to handle “global” events, and Document
, Window
, HTMLElement
, SVGElement
, and MathMLElement
all inherit these.
Unfortunately, the definitions here for addEventListener("error"
and onerror
are used uniquely by Window
. None of the other types inheriting these definitions are correct for error events.
These are the definitions:
interface GlobalEventHandlersEventMap {
// …
"error": ErrorEvent;
// …
}
interface GlobalEventHandlers {
// …
/**
* Fires when an error occurs during object loading.
* @param ev The event.
*
* [MDN Reference](https://developer.mozilla.org/docs/Web/API/HTMLElement/error_event)
*/
onerror: OnErrorEventHandler;
// …
}
// …
type OnErrorEventHandler = OnErrorEventHandlerNonNull | null;
// …
interface OnErrorEventHandlerNonNull {
(event: Event | string, source?: string, lineno?: number, colno?: number, error?: Error): any;
}
Note that MDN link for onerror
that specifically directs to HTMLElement/error_event
: that page says,
Syntax
Use the event name in methods like
addEventListener()
, or set an event handler property.addEventListener("error", (event) => { }) onerror = (event) => { }Event type
The event object is a
UIEvent
instance if it was generated from a user interface element, or anEvent
instance otherwise.
Just a single argument that is either Event
or UIEvent
. Both the five-argument onerror
definition and the single ErrorEvent
argument "error"
definition are wrong for HTMLElement
.
Instead, those definitions are from Window
, and are defined correctly for Window
, including the discrepancy in the arguments between addEventListener
and onerror
. Well, the GlobalEventHandlersEventMap
definition is possibly less than precise:
The event object is a
ErrorEvent
instance if it was generated from a user interface element, or anEvent
instance otherwise.
However, the page notes that all of this is unique to Window
:
Note: For historical reasons,
onerror
onWindow
andWorkerGlobalScope
objects is the only event handler property that receives more than one argument.
The event handler's signature is asymmetric between
addEventListener()
andonerror
. The event handler passed toWindow.addEventListener()
receives a singleErrorEvent
object, while theonerror
handler receives five arguments, matching theErrorEvent
object's properties:
This special behavior only happens for the
onerror
event handler onwindow
. TheElement.onerror
handler still receives a singleErrorEvent
object.
(Side note: the “Element.onerror
” link in that last quote actually goes to HTMLElement
, and according to that page, it’s a UIEvent
or Event
, not an ErrorEvent
, so MDN has some issues here, too.)
Thus, these definitions should only be applied to Window
in lib.dom.d.ts
, and onerror
/addEventListener("error"
for HTMLElement
, SVGElement
, and MathMLElement
should be defined differently. (I can’t actually find definitions of onerror
for MathMLElement
on MDN, nor for Document
which I also see using GlobalEventHandlers
in lib.dom.d.ts
, but I haven’t dug into those cases much.)