querySelector
can return any subtype of Element
. On a webpage this would almost certainly be either HTMLElement
or SVGElement
. The two are not compatible, and yet TypeScript seems happy for me to assign the result of querySelector
to an HTMLElement
type and access properties specific to HTMLElement
. Why doesn't it throw an error?
Here's an example
// why no error on assuming it's going to be HTMLELement
// and not SVGELement or some other Element?
const foo: HTMLElement | null = document.querySelector("*");
if (foo !== null) {
console.log(foo.hidden);
}
This compiles fine, however foo
can actually be an SVGElement
.
If I manually set foo
's type to be SVGElement
then typescript will rightfully complain about accessing the hidden
property.
Why doesn't TypeScript catch the mistaken assumption that the return of querySelector
is necessarily an HTMLElement
?
The signature for the method is
querySelector<E extends Element = Element>(selectors: string): E | null;
By defining the returned type as HTMLElement
(see Type Inference), you've provided the E
generic type. Your code is the equivalent of
const foo = document.querySelector<HTMLElement>('*'); // HTMLElement | null
The only restriction is that E
must extend Element
.