TypeScript-DOM-lib-generator icon indicating copy to clipboard operation
TypeScript-DOM-lib-generator copied to clipboard

[Web API type definition issue] incorrect type definition for `getElementById()`

Open trusktr opened this issue 9 months ago • 4 comments

Summary

incorrect type definition for document.getElementById() and shadowRoot.getElementById()

Expected vs. Actual Behavior

The type definition in lib.dom shows the signature as:

interface Document extends Node, DocumentOrShadowRoot, FontFaceSource, GlobalEventHandlers, NonElementParentNode, ParentNode, XPathEvaluatorBase {
    // ... omitted ...
    getElementById(elementId: string): HTMLElement | null;
    // ... omitted ...
}

The signature should be

interface Document extends Node, DocumentOrShadowRoot, FontFaceSource, GlobalEventHandlers, NonElementParentNode, ParentNode, XPathEvaluatorBase {
    // ... omitted ...
    getElementById(elementId: string): Element | null;
    // ... omitted ...
}

Playground Link

https://www.typescriptlang.org/play/?#code/CYewxgrgtgpgdgFwHQCMTAJ5IJZzjAJwAkAVAWQBkACAXioHIAeAZwDcBzAPkfau2BoAiAGYgQg7gHoujSWy70AUIrAg4zBFV51QkWIlToMAQiTDsBDQFEANjH0IAwgAtsN4KfOWEt+-Ceu7lQAhsxUAMoAagDi0b4OyqrqIHZINiDsABS8uBrBcGAwIMIRMXF2DgCUVJKSVAgEEDBUiWoaWgBMtFS60P5I7DA+Ff4AQhgAksCZ9KIg9NWhpbHx-q3JqelZ7F25CPmFxcvlfojVtVQabjb1jTBAA

Browser Support

  • [x] This API is supported in at least two major browser engines (not two Chromium-based browsers).

Have Tried The Latest Releases

  • [x] This issue applies to the latest release of TypeScript.
  • [x] This issue applies to the latest release of @types/web.

Additional Context

Proof:

// Run this in your console:

document.body.innerHTML = '<svg><g id="foo"></g></svg>'

const g = document.body!.firstElementChild!.firstElementChild

console.log(g instanceof SVGGElement) // true

const g2 = document.getElementById('foo')

console.log(g2 instanceof SVGGElement) // still true (getElementById did not return HTMLElement | null)

The type is also wrong for other types of documents:

interface DocumentFragment extends Node, NonElementParentNode, ParentNode {
    readonly ownerDocument: Document;
    getElementById(elementId: string): HTMLElement | null;
}

trusktr avatar May 15 '25 00:05 trusktr

Can i work on this @saschanaz

Bashamega avatar May 15 '25 03:05 Bashamega

This is intentional, as most of the time the desired result would be HTMLElement. We even had complaint when ShadowRoot did return Element instead of HTMLElement. https://github.com/microsoft/TypeScript-DOM-lib-generator/issues/1067

saschanaz avatar May 15 '25 06:05 saschanaz

By that logic we might as well type event.target as HTMLElement instead of EventTarget which is also totally wrong. I don't think this makes a lot of sense.

trusktr avatar May 18 '25 00:05 trusktr

I hate the current event.target type but this is far more often used on non html contexts than getElementById or parentElement: window, document, xhr, IDBRequest, MediaQueryList...

HolgerJeromin avatar May 18 '25 20:05 HolgerJeromin