TypeScript类型判断疑问:typeof与instanceof用于HTMLElement类型校验的编译差异问题
Great question! Let's break down exactly why your first TypeScript snippet throws a compile error while the second one works as expected.
1. Why the first snippet fails
Your first code uses this condition for the second check:
if (typeof el === typeof this.el) { this.el = el; }
The core issue is how TypeScript interprets typeof this.el during static analysis:
- At runtime,
typeof this.elwould return"object"(since all DOM elements are objects), but TypeScript doesn't treat this as a fixed literal value. Instead, it seestypeof this.elas a generalstringtype (because thetypeofoperator returns a string). - Because of this ambiguity, TypeScript can't use
typeof el === typeof this.elas a valid type guard to narrowelfromstring | HTMLElementto justHTMLElement. It still considerselcould be a string inside thatifblock, hence the error:Type 'string' is not assignable to type 'HTMLElement'.
Side note: There's also a hidden safety issue here—document.getElementById(el) returns HTMLElement | null, but your el property is typed as non-null HTMLElement. You might want to add a check for null to avoid runtime errors, but that's a separate concern from your original question.
2. Why the second snippet works
Your revised code uses:
if (el instanceof HTMLElement) { this.el = el; }
instanceof is a built-in type guard that TypeScript fully recognizes. When you check el instanceof HTMLElement, TypeScript knows that if the condition is true, el must be an instance of HTMLElement (not a string). This correctly narrows the type of el inside the if block, so assigning it to this.el (which expects an HTMLElement) is completely safe—no compile error required.
Bonus: A cleaner alternative
You could also simplify the logic with an else if (or just else) to avoid extra checks entirely. Once you've handled the string case, TypeScript automatically infers the remaining type is HTMLElement:
export default class App { el: HTMLElement; constructor(el: string | HTMLElement) { if (typeof el === "string") { const element = document.getElementById(el); if (!element) { throw new Error(`Element with ID "${el}" not found`); } this.el = element; } else { this.el = el; } } }
内容的提问来源于stack exchange,提问作者xcchcaptain

