专栏名称: 前端从进阶到入院
我是 ssh,只想用最简单的方式把原理讲明白。wx:sshsunlight,分享前端的前沿趋势和一些有趣的事情。
目录
相关文章推荐
知识产权界  ·  2024年代理机构专利预审提交量TOP ... ·  昨天  
知识产权那点事  ·  销售“冒牌”槟榔,金额高达176万余元! ·  昨天  
51好读  ›  专栏  ›  前端从进阶到入院

TypeScript 5.8 正式发布,这些新特性让开发者直呼过瘾!

前端从进阶到入院  · 公众号  ·  · 2025-03-04 18:23

正文

嘿,各位小伙伴们!TypeScript 5.8 已经发布一段时间了,最近我收到不少朋友的私信,都在问:"这次更新的新特性到底有啥用啊?"、"在什么场景下能派上用场?"

今天,我就用最通俗易懂的语言,带大家一起扒一扒这些新特性的真面目,看看它们能如何在我们的日常开发中大显身手!

不管你是 TypeScript 老司机还是新手上路,这篇文章都能帮你快速了解这次更新的精髓。咱们就从这些新特性解决了什么问题,以及在什么实际场景下能派上用场这两个方面来聊聊!

条件类型和索引访问类型的返回检查:告别类型混乱

问题场景

想象一下,你有一个根据选择模式返回不同类型的函数:

// 之前的写法
async function showQuickPick(
    prompt: string,
    selectionKind: SelectionKind,
    items: readonly string[],
): Promise<string | string[]> 
{
    // 实现代码
}

// 使用时需要手动检查类型
let result = await showQuickPick(
    "选择水果",
    SelectionKind.Multiple,
    ["苹果""香蕉""橙子"]
);

// 错误:无法确定 result 是 string 还是 string[]
console.log(`已选择: ${result.join(", ")}`);

TypeScript 5.8 的解决方案

现在,TypeScript 5.8 引入了更智能的条件类型推断机制:

type QuickPickReturnextends SelectionKind> =
    S extends SelectionKind.Multiple ? string[] : string;

asyncfunction showQuickPick<S extends SelectionKind>(
    prompt: string,
    selectionKind: S,
    items: readonly string[],
): Promise<QuickPickReturn<S>> 
{
    // 实现代码
}

// TypeScript 自动推断正确的返回类型
let multipleResult = await showQuickPick(
    "选择水果",
    SelectionKind.Multiple,
    ["苹果""香蕉""橙子"]
); // 类型为 string[]

let singleResult =  await showQuickPick(
    "选择一个水果",
    SelectionKind.Single,
    ["苹果""香蕉""橙子"]
); // 类型为 string

// 现在可以安全地使用 join 方法
console.log(`已选择: ${multipleResult.join(", ")}`);

这种改进不仅让代码更加简洁,还在编译时就能捕获潜在的类型错误,大大提高了代码的可靠性。

CommonJS 终于可以 require() ESM 模块了!

长期以来, Node.js 生态系统中的一个主要痛点是 CommonJS 和 ECMAScript 模块(ESM)之间的互操作性问题:

  • ESM 文件可以导入 CommonJS 文件 ✅
  • CommonJS 文件不能 require() ESM 文件 ❌
    这给库作者带来了巨大挑战,他们要么放弃对 CommonJS 用户的兼容性,要么选择"双重发布"(为 ESM 和 CommonJS 提供单独的入口点),或者干脆停留在 CommonJS 上。但,这一次模块互操作性有重大突破!

Node.js 22 的突破

Node.js 22 放宽了这一限制,允许从 CommonJS 模块中使用 require() 调用 ECMAScript 模块(虽然仍不支持包含顶级 await 的 ESM 文件)。

TypeScript 5.8 的支持

TypeScript 5.8 在 --module nodenext 标志下正式支持这一行为:

// 在 --module nodenext 下,以下代码不再报错
const esmModule = require('./myEsmModule.mjs');

这对库作者来说是个重大利好,他们现在可以在不进行复杂的双重发布的情况下提供 ESM 支持。

如何使用?

  • 如果你的项目运行在 Node.js 22 及更高版本,使用 --module nodenext
  • 对于库作者和旧版 Node.js 用户,建议继续使用 --module node16 或升级到 --module node18

--erasableSyntaxOnly 选项:与 Node.js 无缝协作

Node.js 23.6 引入了 --experimental-strip-types 模式,允许直接运行 TypeScript 文件,但要求所有 TypeScript 特有的语法都不能有运行时语义。换句话说,必须能够轻松地从文件中删除任何 TypeScript 特有的语法,留下一个有效的 JavaScript 文件。

不支持的结构包括:

  • enum 声明
  • 含有运行时代码的命名空间和模块
  • 类中的参数属性
  • 导入别名

TypeScript 5.8 的解决方案

为了帮助开发者确保代码与 Node.js 的这一新功能兼容,TypeScript 5.8 引入了 --erasableSyntaxOnly 标志:

// 启用 --erasableSyntaxOnly 后
class Point {
    constructor(public x: numberpublic y: number) { }
    //          ~~~~~~~~~~~~~~~~
    // 错误! 当启用 'erasableSyntaxOnly' 时,不允许使用这种语法。
}

通过启用这个标志,你可以在编译时就发现潜在的兼容性问题,而不是等到运行时才遇到错误。

声明文件中的计算属性名保留:提升类型准确性

在之前的 TypeScript 版本中,当在类中使用计算属性名时,生成的声明文件可能会出现不一致的问题。TypeScript 5.8 对此进行了改进,现在会在声明文件中保留计算属性名,使其与实际代码保持一致。

之前的问题

export let propName = "answer";

exportclass MyClass {
    [propName] = 42;
}

// 生成的声明文件:
exportdeclarelet propName: string;
exportdeclareclass MyClass {
    [x: string]: number// 泛化为索引签名
}

TypeScript 5.8 的改进

export let propName = "answer";

exportclass MyClass {
    [propName] = 42;
}

// 生成的声明文件:
exportdeclarelet propName: string;
exportdeclareclass MyClass {
    [propName]: number// 保留了原始的计算属性名
}

这一改进使得声明文件更加准确,提高了类型检查的精确度,特别是在使用复杂对象结构时。

性能优化:更快的程序加载与更新

TypeScript 5.8 在性能方面也带来了显著改进,特别是对大型项目的支持:

路径规范化优化

在处理大量文件时,TypeScript 现在避免了不必要的数组分配,直接操作路径索引,减少了重复工作。

配置验证缓存

在编辑过程中,如果项目的基本结构没有变化,TypeScript 将避免重新验证配置选项,从而提高大项目的编辑响应速度。

这些优化对于大型项目尤其重要,可以显著提升开发体验,减少等待时间。

6. 其他重要更新

  • 新增 --libReplacement 标志:

允许开发者禁用默认的库文件替换行为,提供更多自定义选项。 导入断言变更

  • 导入断言变更 在 --module nodenext 中,TypeScript 推荐使用 with 替代 assert 进行导入断言。
// 不推荐
import data from "./data.json" assert { type"json" };

// 推荐
import data from "./data.json" with { type"json" };
  • DOM 类型更新 lib.d.ts 文件进行了更新,可能会影响依赖 DOM 类型的代码库。

如何升级到 TypeScript 5.8?

升级到最新版本非常简单:

npm install -D typescript@latest

如果你使用的是 Visual Studio Code,也可以更新 TypeScript 工具来体验这些新特性。

实际应用案例:提升开发效率的真实例子

案例一:API 客户端库的类型安全

假设你正在开发一个 API 客户端库,需要根据不同的请求参数返回不同的响应类型:

// TypeScript 5.8 之前






请到「今天看啥」查看全文