narrowing 类型收窄基础(含真值与可赋值收窄)
最后更新:2026-10-22
narrowing 类型收窄基础(含真值与可赋值收窄)
联合类型把多种可能揉在一个变量里,用之前必须先"问清楚"它此刻到底是什么类型——这个把宽类型缩小到具体类型的过程叫收窄。TypeScript 通过分析 if、switch、真值判断等控制流,自动把变量收窄到对应分支的类型,之后你才能安全访问这个分支才有的属性。
| 分组 | 收窄与断言 |
|---|---|
| 类型 | 语法 |
| 严格模式 | 不需要 |
ℹ️ 说明 编辑器将 TypeScript 转译为 JavaScript 后运行(不做类型检查);类型检查结果见示例 Output。
📝 语法
function handle(value: string | number | null) {
if (value == null) return; // 收窄掉 null/undefined
if (typeof value === "string") {
value.toUpperCase(); // 这里 value 已收窄为 string
} else {
value.toFixed(2); // 这里 value 已收窄为 number
}
}
⚙️ 参数
| == null | 宽松相等判断会同时筛掉 null 和 undefined,是最常用的空值收窄写法 |
|---|---|
| truthiness | if (value) 这种真值检查会同时剔除 null、undefined、0、""、false、NaN |
返回值:无返回值——收窄是编译期的控制流分析,不会生成任何运行时代码。
▶ 示例
修改下面的代码,点击试一试查看转译运行结果:
输出:
Hello, guest
Hello, guest
Hello, anonymous
Hello, Ada (length 3)
(转译后运行输出;每个分支里能安全访问 name.length 是因为 tsc 已把 name 收窄为 string,运行时只看到值本身)
💡 要点
ℹ️ 说明 收窄完全是编译期行为:TS 沿着代码的执行路径跟踪类型(控制流分析),转译后的 JS 里没有任何"收窄代码"。
⚠️ 注意 真值检查会误伤合法的 falsy 值:0、""、false 也会被 if (value) 剔除。当 0 是有效业务值(如价格、数量)时,应改用 value != null 或显式 typeof 判断。
💡 提示 收窄对局部变量和 const 最可靠;对象属性经过函数调用后收窄可能失效(TS 不知道函数有没有改它),这时把属性先取到局部变量里,或用类型守卫函数。
🏷️ 相关收窄与断言
💡 相关案例
更多案例即将上线。
📚 相关教程
❓ 常见问题
Q 收窄和类型断言(as)有什么区别?
A 收窄由编译器根据你写的检查自动推断,检查和类型是对得上的;断言是你手动"宣布"类型,编译器不再验证。能用收窄就别用断言,后者错了编译器也不会拦。
Q 为什么先判断了 if (!obj.flag),后面 obj.flag 还是可能为 undefined?
A 对属性、方法调用等"可能有副作用"的访问,TS 不会长期保持收窄——中间任何函数调用都可能改掉它。稳妥做法是把值取到 const 局部变量后再判断。
Q null 和 undefined 一次判断能同时排除吗?
A 可以:value == null(宽松相等)同时筛掉两者;也可以用 value != null 反向判空。严格相等 === 需要写两次(=== null 和 === undefined)。