microsoft / microsoft/TypeScript

HTMLElement inherits onerror and addListener("error" definitions that are unique to Window

Abierto
#62,075 1 comentario 1 reacción 2 asignados Reclamado por @RyanCavanaugh Ver en GitHub
Bug Domain: lib.d.ts Help Wanted Needs Human Review
Lenguaje dominante
Go
Estrellas
111k
Forks
14.3k
Merge medio
2 d 4 h
PR fusionados (30 d)
132

Descripción

### 🔎 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

https://www.typescriptlang.org/play/?#code/CYUwxgNghgTiAEYD2A7AzgF3gCwwWwgFEIQ8QUMAueACQBUBZAGWNPIwG4AoL3A1shQB0qEDBhIYACikgAbu2qEFFAJTwAvAD54AbwC+qjvAD0J+GmxIArhGDwUSLGIkwuQA

### 💻 Code

```ts
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:

```ts
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()`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener), or set an event handler property.
>
> ```js
> addEventListener("error", (event) => { })
>
> onerror = (event) => { }
> ```
>
> #### Event type
> The event object is a [`UIEvent`](https://developer.mozilla.org/en-US/docs/Web/API/UIEvent) instance if it was generated from a user interface element, or an [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event) 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`](https://developer.mozilla.org/en-US/docs/Web/API/Window/error_event), 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`](https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent) instance if it was generated from a user interface element, or an [`Event`](https://developer.mozilla.org/en-US/docs/Web/API/Event) instance otherwise.

However, the page notes that all of this is unique to `Window`:

> **Note:** For historical reasons, `onerror` on `Window` and [`WorkerGlobalScope`](https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope) objects is the only event handler property that receives more than one argument.

> The event handler's signature is asymmetric between `addEventListener()` and `onerror`. The event handler passed to `Window.addEventListener()` receives a single [`ErrorEvent`](https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent) object, while the `onerror` handler receives five arguments, matching the [`ErrorEvent`](https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent) object's properties:

> This special behavior only happens for the `onerror` event handler on `window`. The [`Element.onerror`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/error_event) handler still receives a single [`ErrorEvent`](https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent) 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.)

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.