with this code
export default class App {
el: HTMLElement;
constructor(el: string | HTMLElement) {
if (typeof el === "string") {
this.el = document.getElementById(el);
}
if (typeof el === typeof this.el) {
this.el = el;
}
}
}
get compile error info:
Type 'string | HTMLElement' is not assignable to type 'HTMLElement'.
Type 'string' is not assignable to type 'HTMLElement'.ts(2322)
changed code like as follow ,will get no error info:
export default class App {
el: HTMLElement;
constructor(el: string | HTMLElement) {
if (typeof el === "string") {
this.el = document.getElementById(el);
}
if (el instanceof HTMLElement) {
this.el = el;
}
}
}
i'm confused, they should both get error or both get worked.
CodePudding user response:
typeof
can return only undefined
, null
, boolean
, number
, bigint
, string
, symbol
, function
, and object
.
You can see more detail in this docs.
CodePudding user response:
The error is clear, the typeof el
returns one of "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
type at runtime.
At TS compiler time, typeof
becomes a type guard, TS will narrow the type to string | HTMLElement
.
But the instance props this.el
is just HTMLElement
.
You should narrow the type of el
to HTMLElement
, so you need to check it's not string
type.
instanceof
type guards are a way of narrowing types using their constructor function.
el instanceof HTMLElement
statement will narrow the type of el
to HTMLElement
which can be assigned to this.el
.
class App {
el: HTMLElement | null = null;
constructor(el: string | HTMLElement) {
if (typeof el === "string") {
this.el = document.getElementById(el);
}
if (typeof el === typeof this.el && typeof el !== 'string') {
this.el = el;
}
}
}
CodePudding user response:
You should know the difference between typescript's typeof
and javascript's typeof
. According to this doc, when you use typeof
in an expression context, you are actually using the javascript one. Thus:
if (typeof el === typeof this.el) {
this.el = el;
}
you end up checking two entities both having the type "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
.
To help typescript infer the type correctly, you must use an explicit type in your condition:
if (typeof el === 'object') {
this.el = el;
}
But in your case, the best way is to use an else
statement:
if (typeof el === 'string') {
this.el = document.getElementById(el);
} else {
this.el = el;
}