TypeScript 3.4-3.7 新增特性详解:可选链、空值合并与断言签名
本文详细介绍 TypeScript 从 v3.4 到 v3.7 引入的七项核心功能,包括可选链操作符、空值合并运算符、递归类型别名、断言签名、Promise 错误提示优化、Unicode 标识符支持及增量编译。通过对比新旧版本代码示例,解析各特性在解决嵌套数据访问、类型保护及构建性能方面的实际应用场景。
TypeScript 持续演进,不断引入提升开发体验与代码安全性的新特性。
这些功能自 v3.7 版本起可用。
在处理深层嵌套数据结构时,开发者常面临访问路径过长且易出错的问题,嵌套层级越深,代码逻辑越显繁琐。
以访问 address 为例,传统方式需遍历 data.customer.address,且需处理 data 或 customer 可能为 undefined 的情况。通常需借助 && 运算符或类似技巧逐层检查各层级是否存在,代码冗长。
现在,开发者可使用 ?. 运算符进行选择性数据访问。该机制确保若链中任一父级对象未定义,则直接返回 undefined,从而避免运行时崩溃。
// v3.7 以前
if (data && data.customer && data.customer.address) {
const {address} = data.customer
const fullAddress = `${address.street}, ${address.city}, ${address.state }${address.zipcode}`
}
// v3.7
// data access
const address = data?.customer?.address
const fullAddress = `${address?.street}, ${address?.city}, ${address?.state } ${address?.zipcode}`
// 也适用于数组
customers?.[0]?.['address']
// 检查方法是否已定义并调用
customer.approve?.()
空值合并运算符提供了更精确的逻辑判断方式。
该功能同样自 v3.7 版本起可用。
空值合并运算符(??)是逻辑或运算符(||)的替代方案。当左侧操作数为 null 或 undefined 时,它返回右侧表达式。与 || 的区别在于:|| 是布尔或运算符,旨在返回第一个非 false 值。这可能导致意外结果,例如当数字 0 或空字符串作为有效输入时,会被误判为 false。
// 以前
passPhrase = data.inputString || 'Unknown' //不会接受 "" (空字符串)
passCode = data.number || '-1111' // 不会接受 0
rememberMe = data.rememberFlag || true // 将会总是 true!!!
// 现在
passPhrase = data.inputString ?? 'Unknown' //仅在 inputString 未定义时为 Unknown
passCode = data.number ?? '-1111' // 0 可以通过
rememberMe = data.rememberFlag ?? true // false 是有效值
通过这种方式,可以明确区分 undefined 与 false 的值,确保 0 或空字符串等有效值不被错误覆盖。
递归类型别名解决了复杂数据结构的定义难题。
该功能自 v3.7 版本起可用。
现实世界中的许多数据类型具有递归特性。例如处理分层数据时,常发现相同类型数据的重复模式。JSON 是典型例子,其本质为哈希映射,而映射本身可包含另一个映射或映射数组。
在 v3.6 之前,若需定义简单的 JSON 类型,必须采用特定的接口与类型组合方式。
interface JSONObject { [x: string]: JSONValue; }
interface JSONArray extends Array<JSONValue> { }
type JSONValue = string | number | boolean | JSONObject | JSONArray
若尝试将第 1 行和第 2 行的类型在像第 3 那样内联,则可能出现以下错误:Type alias JSONValue circularly references itself。
在 v3.7 中,该问题已有效解决,开发者可以像下面这样简单地进行编码:
type JSONValue = string | number | boolean | { [x: string]: JSONValue } | Array<JSONValue>
断言签名增强了类型保护的能力。
该功能自 v3.7 版本起可用。
TypeScript 具备类型保护机制,可与 JavaScript 中的 typeof 和 instanceof 运算符良好配合。这有助于为函数参数添加前提条件,将其限制为特定类型。
让我们写一段把上面提到的这些东西都用到的代码,通过添加类型保护来确保给定的输入是日期,并从中提取年份:
function isDate(input: unknown) : asserts input is Date {
if (input instanceof Date)
return;
else
throw new Error('Input must be a Date!');
}
function getYear(input: unknown) : number {
isDate(input);
return input.getFullYear() // TypeScripts knows that input is Date
}
console.log(getYear(new Date('2019-01-01')));
console.log(getYear('2019-01-01'));
上面的代码看起来很不错,但 TypeScript 仍然会提示 getFullYear 在未知类型上不可用。
从 v3.7 开始,TypeScript 添加了一个名为 asserts 的新关键字,它能够使编译器从断言起就知道正确的类型。对于断言函数,应该添加 asserts <param> as <type> 而不是返回类型。
这样,如果断言通过,TypeScript 将假定参数是前面定义的类型。修改后的代码如下所示:
function isDate(input: unknown) : asserts input is Date {
if (input instanceof Date)
return;
else
throw new Error('Input must be a Date!');
}
function getYear(input: unknown) : number {
isDate(input);
return input.getFullYear() // TypeScripts knows that input is Date
}
console.log(getYear(new Date('2019-01-01')));
console.log(getYear('2019-01-01'));
Promise 错误反馈机制得到显著改进。
从 3.6 起改进。
在代码中直接使用 Promise 而忘记使用 await 或 then 是常见的错误,如下所示:
interface Customer {
name: string
phone: string
}
declare function getCustomerData(id: string): Promise<Customer>;
declare function payCustomer(customer: Customer): void;
async function f() {
const customer = getCustomerData('c1')
payCustomer(customer)
}
以前的 TypeScript 完全不了解 Promise,并显示一条与其无关的错误消息,如下所示:

从 v3. 6 开始,编译器变得非常聪明,可以建议你应该兑现 Promise。注意最新的编译器是如何处理相同的错误的:

下面简单讨论一下不需要深入了解细节的一些功能:
Unicode 标识符支持扩展了命名规范。
该功能自 v3.6 版本起可用。
const hello = "world"
上面的代码可能不能够在早期版本的 TypeScript 上编译,但是现在你可以从更广泛的 unicode 集中定义标识符。
增量编译大幅提升了大型项目的构建效率。
该功能自 v3.4 起可用。
如果你在大型项目上使用 TypeScript,则编译器可能需要很长时间才能响应你对该代项目中文件所做的更改。现在有了新的 --incremental 标志,你可以将其添加到 tsc(typescript 编译器)命令行中,这个命令行将会递增地编译修改过的文件。
TypeScript 通过把自从上次编译以来的项目信息保存在代码库内的本地缓存目录中来实现这一目的。在 react 代码库上,一定要记住在 Webpack 或 Parcel 进行正确的配置,这样才能在构建管道中利用增量编译。
以上就是 7 个好用的 TypeScript 新功能的详细内容,更多关于 TypeScript 新功能的资料请关注本站其它相关文章!
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








