Search code examples
typescriptstrong-typing

Why is document.body not a HTMLBodyElement?


Visual Studio, hint that document.body is a HTMLElement, and not a HTMLBodyElement, why is that? - I haven't had any luck searching for an answer.

class Test {
    documentBody1: HTMLBodyElement;
    documentBody2: HTMLElement;

    constructor(){
        this.documentBody1 = document.body; //wrong
        this.documentBody2 = document.body; //right
    }
}

Solution

  • The type of the property document.body is HTMLElement, but in most cases it refers to an object that is actually an HTMLBodyElement.

    So why is document.body not typed HTMLBodyElement? Because in some documents, it may refer to an HTMLFrameSetElement. HTMLElement is the common supertype of HTMLBodyElement and HTMLFrameSetElement.

    More at document.body in the spec.


    In a comment, icl7126 asks a good question:

    I'm wondering why is there no null? It will be null when document is not loaded yet...

    My guess is pragmatism. There's a lot of pragmatism rather than idealism in the TypeScript community (and the project itself). Since people almost never run code interacting with the DOM before the body is present, rather than making everyone add an almost-certainly-unnecessary guard or non-nullish assertion when using document.body, the person or people who defined that TypeScript type went with HTMLElement rather than HTMLElement | null. It's not perfectly correct, but it's a balance between correct and useful.