在 JavaScript 中,像 if 这样的结构会首先将其条件强制转化为布尔类型来使其有意义,再选择其对应的分支。
像这些值:
0
NaN
""
(空字符串)0n
( bigint
version of zero)null
undefined
都被强制定义为 false,其他值均为true。
利用这种特性是相当有用的,特别是为了防范 null 或未定义的值。作为一个示例,让我们尝试将其用于 printAll 函数
function printAll(strs: string | string[] | null) {
if (strs && typeof strs === "object") {
for (const s of strs) {
console.log(s);
}
} else if (typeof strs === "string") {
console.log(strs);
}
}
strs 的类型可能为 null,但不幸的是,在JavaScript中,如果用typeof来判断 null 的类型,其结果和Array一样,为 “Object” ,这就使得我们无法仅通过 typeof 的类型守卫来提出 null 的情况
在这里 ,使用 if (strs && typeof strs === "object") 这种写法可以通过判断 strs 的真值来处理 null 产生的影响,这就是真值窄化的一个体现
记住,对基本类型进行真值检查往往容易出错,例如
function printAll(strs: string | string[] | null) {
// !!!!!!!!!!!!!!!!
// DON'T DO THIS!
// KEEP READING
// !!!!!!!!!!!!!!!!
if (strs) {
if (typeof strs === "object") {
for (const s of strs) {
console.log(s);
}
} else if (typeof strs === "string") {
console.log(strs);
}
}
}
我们将整个函数体都丢进了一个真值检查中,但这有一个潜在问题:我们无法再正确处理空字符串的情况。(因为空字符串的布尔值为 false)
最后关于真值窄化要说的是使用 “!” 进行布尔否定会从否定的分支中过滤掉值。