Skip to content

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

Open

Description

@trusktr

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

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

Have Tried The Latest Releases

  • This issue applies to the latest release of TypeScript.
  • 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;
}

Activity

  1. Bashamega commented on May 15, 2025

    @Bashamega
    Contributor
  2. saschanaz commented on May 15, 2025

    @saschanaz
    Contributor

    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. #1067

  3. trusktr commented on May 18, 2025

    @trusktr
    Author

    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.

  4. HolgerJeromin commented on May 18, 2025

    @HolgerJeromin
    Contributor

    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...

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions