先记住这个答案
if(value) 会按 JavaScript 真值规则分支,TypeScript 基于这条规则收窄候选,但它不是只排除 null 和 undefined。零、空字符串、false、NaN 等值也会走假值分支。如果分页偏移允许零、表单允许空字符串或开关允许 false,使用真值判断会误把有效输入当作缺失。仅检查空值时应明确比较 null 和 undefined,或按约定使用 value != null;提供默认值时也应区分只处理空值的 ?? 与处理全部假值的 ||。
- 真值条件会同时排除多种合法业务值
- 仅判断缺失时应表达 null 与 undefined 的规则
- 默认值运算符也必须与有效值集合一致
为什么表单和分页容易中招
分页偏移零表示从第一项开始,计数零表示确实没有结果,开关 false 表示明确关闭。这些都与用户没有提交字段不同。若把它们一起送进缺省逻辑,页面可能显示错误默认值,甚至把关闭状态重新打开。
示例对可选数字分别使用真值和空值判断。前者把零当成默认值,后者保留零。类型检查并不能替作者决定业务语义,即使两种函数都通过编译,也必须用零和空值这样的边界输入验证实际行为。
function truthyDefault(value: number | null | undefined): number {
return value ? value : 10;
}
function nullishDefault(value: number | null | undefined): number {
if (value === null || value === undefined) return 10;
return value;
}
const first = truthyDefault(0);
const second = nullishDefault(0);
function compactDefault(value: number | null | undefined): number {
return value ?? 10;
}
const third = compactDefault(0);前两个函数对零分别得到十和零,显式空值判断准确保留业务输入。compactDefault 对参数使用空值合并,零会原样保留,null 或 undefined 才会得到默认值十。
假值分支中还可能保留什么类型
对于 string | undefined,真值分支可以排除 undefined,但反向分支仍可能是空字符串,所以不能把 else 自动当成 undefined。宽基础类型无法总是表达仅剩空字符串这样的精确集合,应以编译器在当前位置提供的类型为准。
同样,数字真值判断会把 NaN 和零排除,却不会验证正负范围、整数性或有限性。想要合法页码,应写出真正的数值约束;想要非空白字符串,还要考虑 trim 后的结果。把业务规则交给一个 if(value) 往往过于含糊。
默认值与可选链也要审查语义
逻辑或会在左侧为任意假值时选择右侧,空值合并仅针对 null 和 undefined。默认超时时间允许零表示禁用时,两者可能造成明显差异。可选链也只在空值位置短路,并不会把 false 或零视为不存在,不能与真值判断混用概念。
可以为公共工具明确约定缺失值,并测试零、空串、false、null 和 undefined 是否按各自协议处理。不要建立一个到处复用的通用有值函数却不说明它排除什么;数据类型不同、业务含义不同,合法输入集合通常也不相同。
容易答错的地方
- 进入 else 就说明值是 null 或 undefined
- 假值分支还可能包含零、空串、false 或 NaN,具体取决于原类型;应按真实缺省规则检查,不能把它们直接当作同一种缺失。
- 把 || 全部换成 ?? 就一定修好
- 只有默认值规则确实只针对空值时才合适;如果业务明确将空串视为未填写,还需独立处理字符串规则并覆盖相应边界测试。
面试官还会怎么问?
空数组和空对象会进入真值分支吗?
会,它们在 JavaScript 中是真值;判断集合是否为空需要检查长度或明确字段数量,不能只根据对象引用的真假判断内容。
为什么 if(value) 后数字类型仍显示 number?
类型系统没有为所有数字子集提供独立可见类型,运行时虽然排除了部分假值,静态展示仍可能是宽 number,不能据此推断检查没有执行。
字符串只有空格时真值判断能拒绝吗?
不能,空格字符串本身是真值;若表单要求非空白内容,应按规范清理或检查字符,同时明确是否保留用户原始输入。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。