在 JavaScript 中,像 if 这样的结构会首先将其条件强制转化为布尔类型来使其有意义,再选择其对应的分支。

像这些值:

都被强制定义为 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)

最后关于真值窄化要说的是使用 “!” 进行布尔否定会从否定的分支中过滤掉值。