[Typescript] The Inference Mystery Solved
When we pass in "div"
to document.querySelector
, it returns an HTMLDivElement
or null
.
Similarly, when we pass it "span"
we're getting an HTMLSpanElement
.
So we're getting nice specific types when we pass in div
and when we pass in span
.
However, when we pass in "div.foo"
, we'll get back either element
or null
.
import { Equal, Expect } from "../helpers/type-utils";
const divElement = document.querySelector("div");
const spanElement = document.querySelector("span");
/**
* Your challenge: figure out why divElement2 is NOT
* of type HTMLDivElement.
*/
const divElement2 = document.querySelector("div.foo");
// ^? Element | null
type tests = [
Expect<Equal<typeof divElement, HTMLDivElement | null>>,
Expect<Equal<typeof spanElement, HTMLSpanElement | null>>,
Expect<Equal<typeof divElement2, HTMLDivElement | null>> // doesn't pass
];
Check how `querySelector` is defined:
querySelector<K extends keyof HTMLElementTagNameMap>(selectors: K): HTMLElementTagNameMap[K] | null;
querySelector<K extends keyof SVGElementTagNameMap>(selectors: K): SVGElementTagNameMap[K] | null;
querySelector<E extends Element = Element>(selectors: string): E | null;
Because it is using HTMLElementTagNameMap[K]
, but HTMLElementTagNameMap['div.foo']
cannot find a value.
So solution: const divElement2 = document.querySelector<HTMLDivElement>("div.foo");