前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库TypeScript 等值收窄 严格相等 null undefined
TyTypeScript类型收窄

TypeScript 的等值收窄如何工作,value != null 为什么能排除两种空值?

等值判断给出了两个值之间的关系,编译器可以利用这个关系排除不可能的候选。

前端进阶之旅 · 一题精讲更新于 2026.09.06
TypeScript#类型收窄#类型系统
先看核心答案读代码示例
理解线索

从相等关系提取类型信息

  1. 共同候选成功比较后保留双方都可能具有的类型
  2. 具体标签与确定字面量比较以选择相应分支
  3. 空值约定明确需要排除一种还是两种缺失状态

等值比较不会转换变量的存储类型,运行时隐式转换规则也不能任意推广为可靠收窄。

核心回答

先记住这个答案

当两个联合类型的值通过 === 判断相等,TypeScript 可以保留两者共有的可能类型,例如 string | number 与 string | boolean 相等时,成功分支可收窄到 string。与具体字面量比较也能排除其他候选,switch 利用同类标签信息。value != null 是一个常见的特定用法,按 JavaScript 规则同时排除 null 和 undefined;value !== null 则只排除 null。这个空值习惯不代表所有非严格相等都具有同样清楚的类型关系,其他隐式转换比较仍应谨慎。

  • 严格相等可以建立双方共同候选的证据
  • != null 同时排除 null 和 undefined
  • !== null 不会顺带排除 undefined

严格相等为什么能缩小双方范围

一个值可能是文本或数字,另一个可能是文本或布尔值。严格相等不会把数字转换为字符串,也不会把布尔值变成数字,因此成功时共同候选只剩文本。分支内可以对两边使用字符串方法,而失败分支并不能简单断言两边都不是字符串。

示例把这种共同候选与空值检查放在一起展示。空值函数保留零,避免真值判断的误伤。另一个函数只排除 null,故 undefined 仍然存在,不能立即执行数字格式化;这里的预期错误帮助区分两个看似相近的操作符。

共同类型与两种空值检查TypeScript
function compare(a: string | number, b: string | boolean) {
  if (a === b) return a.toUpperCase() + b.toLowerCase();
  return 'different';
}
function format(value: number | null | undefined) {
  if (value != null) return value.toFixed(1);
  return 'missing';
}
function onlyNull(value: number | null | undefined) {
  if (value !== null) {
    // @ts-expect-error undefined 仍没有被排除
    return value.toFixed(1);
  }
}

严格相等的成功分支保留双方的字符串能力,非严格空值比较同时移除两种空值。只排除 null 的反例应报可能为 undefined,而不是被误认为已经完成判空。

失败分支没有成功分支那么强的结论

两个字符串内容不同也会让相等判断失败,因此 a !== b 不能证明它们一定属于不同基础类型。收窄利用的是能够从运行时关系可靠推出的事实,而不是把成功分支的结论机械取反到每个变量上。阅读复杂条件时要考虑完整候选组合。

对象的严格相等比较主要检查引用身份,不会逐字段比较结构。两个独立创建但内容相同的对象通常不相等;接口结构兼容也不会使它们在运行时自动成为同一个对象。需要按业务标识匹配时,应比较明确字段并处理字段有效性。

switch 与空值风格如何选择

有限字面量状态用 switch 便于组织分支,并可结合 never 检查遗漏。只处理单个空值边界时,显式比较往往更简洁。团队若禁止非严格相等,可以写 value !== null && value !== undefined,保持相同的空值排除意图。

不要把 != null 的特殊便利推广到数字字符串等其他宽松比较。隐式转换可能让结果超出阅读者预期,也不一定提供想要的静态关系。涉及用户输入的数值转换,应显式解析并校验结果,使转换、失败处理和类型证据都可见。

回答前,多想一步

容易答错的地方

!== null 可以当作同时检查未定义
它只排除 null,undefined 仍可能到达后续代码;如果两种都表示缺失,应分别比较或按团队规则使用非严格空值比较。
相等失败就说明双方类型不同
相同类型的两个不同值也会比较失败,尤其是字符串和对象引用;应根据完整值关系推导,不能只把成功分支的类型结论反转。
试着用自己的话回答

面试官还会怎么问?

为什么不直接用 if(value) 排除空值?

真值检查还会过滤零、空串和 false 等值;只有它们都应该被排除时才符合业务语义,否则明确空值比较更加准确。

switch 的 case 能改变原来的值吗?

分支匹配只选择执行路径并提供类型信息,不会转换原值;若 case 中有实际赋值,那是另一项运行时操作,需要单独分析。

NaN 能用等于自身来识别吗?

NaN 的相等行为比较特殊,业务检查通常使用 Number.isNaN 更清楚;还要区分只拒绝 NaN 与要求有限数字这两种验证目标。

从一道题,走向一组知识

把知识连起来

类型收窄

TypeScript 用 if(value) 判空为什么会漏掉 0 和空字符串?

对照真值判断为何会丢失有效零值与空串

类型收窄

TypeScript 类型收窄是什么,为什么同一个变量在不同位置类型不同?

理解成功与失败路径如何共同影响当前位置类型

参考资料

  • TypeScript:Equality Narrowing

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 严格相等为什么能缩小双方范围
  3. 失败分支没有成功分支那么强的结论
  4. switch 与空值风格如何选择
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑