TypeScript 3.7 核心新特性详解:可选链、空值合并与未调用函数检查
本文深入解析 TypeScript 3.7 版本中的三个关键新特性。首先介绍可选链操作符(?.)如何简化深层对象属性的安全访问;其次详解空值合并操作符(??)与逻辑或(||)在处理 falsy 值时的区别,避免默认值误赋;最后探讨未调用函数检查功能,帮助开发者提前发现属性与方法调用的逻辑混淆。此外还简述了扁平化错误报告、文件级 @ts-nocheck 等易用性改进,助力项目迁移与代码质量提升。
前言
TypeScript 3.7 正式发布已有一段时间,在此期间,笔者正专注于手头项目的 TypeScript 迁移工作,因此对每一次版本更新都保持着高度关注。
相较于之前的几个主要版本,TypeScript 3.7 属于一个较小的发布版本,但其中引入的若干特性对提升代码质量具有显著作用。
Optional Chaining
该版本首先支持了可选链操作符(Optional Chaining),中文译名略显生硬,故此处直接使用英文术语。
此特性源自 ES2019,具体规范可参考相关文档。
作为 JavaScript 的超集,TypeScript 预先实现该特性符合预期,其基本用法如下:
a?.b();
上述代码等价于:
if(a) a.b();
// 或者
a && a.b()
若涉及多层嵌套,例如 b 本身也是对象且需继续调用 c(),写法如下:
a?.b?.c()
即便按上述方式书写,代码仍非绝对安全,因为 b() 中的 b 可能为空值,直接调用将抛出异常。为确保绝对安全,应写作:
a?.b?.();
需正确理解“可选”的含义:在类型声明中,通过 ? 修饰的属性表示该类型可能包含可为空值的属性。这意味着 ?. 不会针对不符合类型声明的属性进行调用,例如:
interface A {}
const a: A = {};
a?.b?.(); // Property 'b' does not exist on type 'A'
除非将 A 接口的声明修改为:
interface A {
b?: any
}
该特性在工程实践中意义重大,它允许开发者用更少的 if 断言语句或 && 操作符实现相同的安全访问效果。
Nullish Coalescing
其中文译名为双问号操作符,因其语法形式为 ??,形象直观。
该操作符的核心功能是为空值指定默认值,示例如下:
let a = b || 'foo'
当 b 为空值时,由于 || 操作符的特性,a 的值会被赋予 foo。若改用 ?? 操作符改写,如下:
let a = b ?? 'foo'
表面看来两者无别,实则隐含问题:|| 对“空值”的定义不仅包含 null 和 undefined,还包括 false、0 等逻辑上的 falsy 值,这可能导致意外结果,例如:
const b = 0
let a = b || 'foo'
// a 为 'foo'
在此示例中,期望 a 仅在 b 为真正的空值(null 或 undefined)时赋予默认值,a 应等于 0。但实际运行结果为 foo,因为 b=0 在 || 操作中会被解释为 false。笔者曾在实际项目中开发验证码组件时因此踩坑,调试耗时良久。
使用 ?? 操作符则可避免此类问题。
Uncalled Function Checks
许多开发者可能遇到过因缺乏有效命名规范,导致断言属性与断言方法混用的情况,例如:
class A {
isFoo(): boolean {
return false;
}
}
function test(a: A) {
if (a.isFoo) {
...
}
}
若本意是通过调用 a.isFoo 获取断言值,此处明显存在逻辑错误。正确用法应为 if (a.isFoo()),而非直接 if (a.isFoo)。后者在语法上无误,但逻辑上会被断言为 true。TypeScript 3.7 发布后,编译器将尝试辅助发现此类问题。
尽管如此,仍建议针对断言方法和属性制定统一命名规范,例如以 isXXX 表示属性,assertXXX 表示方法。
其他
其余变更主要涉及易用性提升,包括:
- Flatter Error Reporting:将冗长重复的类型错误日志压缩为单条、更准确且精简的错误信息。
- 文件级 @ts-nocheck:此前该注解仅支持行内级别,现扩展至文件级别。
- 递归类型声明:支持在类型声明中使用递归语法定义更复杂的类型,如 JSON 类型。
- 对 JS 文件提供 declaration 支持,以降低从 JavaScript 项目迁移至 TypeScript 的成本。
以上为 TypeScript 3.7 中值得关注的三个新特性的详细解析,更多关于 TypeScript 3.7 新特性的资料,敬请关注本站其他相关文章。
JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
JS 解压出现乱码或报错怎么解决?
2026-11-05 12:32:38
JS 中 startsWith、indexOf 与正则判断字符串前缀的对比
2026-11-04 22:19:43
JS解析Excel后怎么将数据转换为JSON格式
2026-11-04 20:58:28








