Skip to content

Conversation

@cosmic-pixel-painter
Copy link

@cosmic-pixel-painter cosmic-pixel-painter commented Jan 11, 2026

This PR fixes microsoft/TypeScript#62075. and is a result of the comment left on the PR over here, which I closed. Thanks for the advice on that 🙏 . I re-read your comment and figured out a path forward. I also dropped UIEvent from this PR.

Recap

As a recap, this handles this bug report here. The issue is that HTMLElement.onerror (and other element onerror handlers) uses the incorrect interface OnErrorEventHandler, which has the signature:

type OnErrorEventHandler = (
  event: Event | string,
  source?: string,
  lineno?: number,
  colno?: number,
  error?: Error
) => any;

This causes a type error when assigning a Event-based handler:

const div = document.createElement("div");
div.onerror = (event: Event) => {  // TS Error!
  // Type '(event: Event) => void' is not assignable to type 'OnErrorEventHandler'.
  // Types of parameters 'event' and 'event' are incompatible.
  // Type 'string | Event' is not assignable to type 'Event'.
};

It should be that window.onerror uses OnErrorEventHandler and elements uses the Event object.

Changes

  • I ended up changing GlobalEventHandlers.onerror to use an event-based handler instead of OnErrorEventHandler. I did this by updating events.kdl to use Event instead of ErrorEvent.
  • I then overrode window.onerror to keep using OnErrorEventHandler since Window is the only place where this handler signature is expected. The change is in overridingTypes.jsonc.
  • This caused duplicate declarations since Window extends GlobalEventHandlers and both define onerror differently. This was happening in the global scope "polluter". I fixed this by tracking already emitted members in emitAllMembers.
  • I then updated isCovariantEventHandler to not skip properties that have an explicit overrideType. This was need to handle Window's onerror override.

Before/After

Before:

interface GlobalEventHandlers {
  onerror: OnErrorEventHandler;
}
// Window inherits OnErrorEventHandler from GlobalEventHandlers

After:

interface GlobalEventHandlers {
  onerror: ((this: GlobalEventHandlers, ev: Event) => any) | null;
}

interface Window extends GlobalEventHandlers {
  onerror: OnErrorEventHandler;  // Explicit override
}

Testing

I added the onerror.ts test file and updated the eventlistener.ts test file.

Other Thoughts

This has been a crazy and fun bug to hunt down. I think I nailed it this time 😂

@github-actions
Copy link
Contributor

Thanks for the PR!

This section of the codebase is owned by @saschanaz - if they write a comment saying "LGTM" then it will be merged.

@cosmic-pixel-painter cosmic-pixel-painter changed the title Dom base event handler Element error event handler Jan 11, 2026
@cosmic-pixel-painter
Copy link
Author

cosmic-pixel-painter commented Jan 12, 2026

@saschanaz I was able to fix it using the KDL file and didn't need to touch the overrideType 🎉 . I think this nails it 🔨

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants