目录

在一次拉取请求中,共享的 TypeScript 接口发生了变更。应用在本地正常启动,测试也全部通过,于是开发者推送了分支。然而,CI 却失败了。原来,仓库中的另一个包仍在使用旧接口。

TypeScript 代码能够正常运行,并不意味着类型一定正确。团队需要单独进行类型检查,而检查耗时会影响开发者运行检查的频率。

2026 年 10 月 10 日发布的 Bun 1.4.3,将这一问题作为本次发布的重点。据所提供的报告,Anthropic 的 JavaScript 运行时内置了 TypeScript 类型检查器,可通过 bun check 使用。它给出的性能承诺相当大胆:运行速度超过 TypeScript 7 的 3 倍,内存占用约为其一半到四分之一,甚至更低。

这些数据值得评估。但不应仅凭这些数字就替换现有的 CI 检查。

Bun 1.4.3 新增了什么#

Bun 已经支持加载 TypeScript、将其转译为 JavaScript,以及执行转换后的代码。类型检查则承担着不同的职责。

转译是移除或转换 TypeScript 语法,使程序能够运行的过程。类型检查则用于检查程序是否遵循所声明的类型关系。即使程序在已测试的执行路径上运行正常,其他地方仍可能存在类型错误。

Bun 1.4.3 中值得关注的新功能,就是一个执行后者的内置命令。

snippet.txt
bun check

所提供的报告称,该命令接收 TypeScript 文件并验证其类型。在将其引入现有项目之前,应先查阅发布文档,确认支持的运行方式、配置处理方式和命令行选项。

在考虑采用时,这一区别很重要。对于已经使用 Bun 运行脚本的团队,它可能提供了一种新的便捷类型检查方式。使用其他运行时的团队,只要项目需求得到支持,也可以单独评估这个类型检查器。更换检查源代码的工具,并不要求同时更换运行应用的运行时。

因此,需要确认的问题很具体:这个类型检查器能否在减少耗时和内存占用的同时,准确检查自己的仓库?

速度声明值得关注,但需要明确比较条件#

据报告,Bun 的类型检查器比用 Go 实现的 TypeScript 7 快 3 倍以上。

相比超越传统的 JavaScript 类型检查器实现,这是一项更严格的比较。TypeScript 7 迁移到 Go,本身就是为了提升性能。而 Bun 声称,相比这个新的参照对象,它还能大幅缩短耗时。

为了理解这一提升的量级,可以想象一项目前耗时 90 秒的检查。如果速度恰好提升到原来的 3 倍,同样的处理就能在 30 秒内完成。这只是用于说明的例子,并非 Bun 此次发布中测得的结果。

内存节省可能同样重要。如果类型检查器的内存占用减半,就更容易在 CI 运行器上与测试、构建并行执行。如果还能进一步降低占用,也可能有助于那些目前已接近运行器内存上限的仓库。

不过,所提供的资料没有说明基准测试使用的硬件、全部测试项目、缓存状态或测量步骤。也没有说明,所报告的优势是否同样适用于小型应用、大型 monorepo,以及使用复杂泛型的项目。

应将发布中给出的数字视为尝试的理由。对自己的工作流程真正重要的结果,需要在自己的仓库中获得。

“100% 符合性”实际说明了什么#

只有当类型检查器确实能检测出团队期望发现的错误时,性能才有价值。

所提供的报告介绍了两类兼容性验证。首先,据称 Bun 通过了 TypeScript 7.0.2 的全部符合性测试。其次,团队选取了 72 个包含错误的开源 TypeScript 文件,对比 TypeScript 与 Bun 的结果,发现了 1 处差异。

通过语言实现的符合性测试套件,是一项有意义的依据。它表明,在这些测试覆盖的语言行为上,两者具有广泛的一致性。

不过,这些结果能说明的范围仍然有限。测试套件包含的用例数量有限。即使全部通过,也不能证明源文件、编译器配置、包声明和依赖结构的任意组合都会产生相同的行为。

对 72 个文件的比较则提供了另一类依据:在符合性测试套件之外选取的源代码示例中,结果也基本一致。但报告中的那处差异仍需调查。所提供的文字没有解释,它究竟是漏报了诊断信息、多报了诊断信息,还是仅仅在错误显示方式上存在差异。

这些情况的影响各不相同。如果只是消息内容发生变化,可能稍微调整工具即可。如果漏报了错误,则可能削弱发布判定的可靠性。

实际应用中的标准,是项目所依赖的行为保持一致。这包括在实际使用的配置下,既能拒绝错误代码,也能接受正确代码。

加快类型检查可以改善工作流程#

类型检查器变快的直接好处,是减少等待时间。能否带来更大的价值,则取决于运行检查的负担减轻后,开发者的行为是否会随之改变。

很快就能完成的检查,更容易在提交前运行。耗时较长的检查则容易被推迟到 CI 阶段,此时反馈到来时,开发者往往已经转去处理其他工作。

可以考虑以下两种情况。

  • 开发者修改共享 API 后,在本地运行完整的类型检查,修复受影响的调用方,然后再推送。
  • 开发者先推送并等待 CI,开始其他工作后,再回头处理这次变更。

采用前一种工作流程时,相关代码和决策依据还留在开发者脑海中。加快类型检查,有助于维持这种工作方式。

不过,类型检查器的提速比例,并不等于整个 CI 耗时的缩短比例。如果一条 10 分钟的流水线中,类型检查占 90 秒,那么将其缩短到 30 秒,只能节省 1 分钟。安装依赖、测试和构建仍会占用其余时间。

并行执行会让情况更加复杂。如果 CI 的完成时间取决于一个耗时更长的测试任务,那么即使类型检查变快,资源消耗有所降低,最终完成时间也可能保持不变。

先单独测量类型检查器,再测量整个流水线。

在现有仓库中开展四阶段评估#

有价值的试用需要留下其他工程师能够复核的依据。应缩小评估范围,以便出现问题时定位原因。

1. 记录当前配置#

记录 TypeScript 版本、Bun 版本、操作系统,以及可用的 CPU 和内存。也要准确记录当前用于类型检查的命令。

如果所用工具支持,应测量运行耗时和峰值内存占用。多次运行检查,并记录每次是否使用了现有缓存。

避免让一个工具在无缓存状态下运行,另一个工具在有缓存状态下运行,然后比较结果。这可能夸大与类型检查器本身无关的差异。

2. 比较诊断结果#

针对相同的提交和配置,运行两个类型检查器。

先从能够通过现有检查的版本开始。然后,在临时分支中故意加入一些有代表性的错误,例如错误的参数、不兼容的赋值、无法解析的导入,以及错误的返回值类型。

这些示例无法证明完全兼容,但仍能确认类型检查器能否处理团队期望发现的一些问题。

调查所有结果不一致的情况。记录受影响的文件、配置和最小复现示例。在弄清楚之前,不要将其视为无害差异。

3. 测试仓库特有的复杂情况#

根据实际代码库选择用例。monorepo 可能高度依赖包之间的边界和项目引用。前端应用则可能依赖生成的类型声明和框架专用工具。

尤其要关注模块解析、路径别名、第三方类型声明文件,以及与严格性相关的配置。不要认为符合语言规范就能保证所有集成细节都受支持,应查阅文档确认支持情况。

如果现有 TypeScript 命令还负责输出类型声明,或承担其他必需的构建任务,就要明确如何接替这些职责。高速类型检查命令并不会自动替代编译器的所有用途。

4. 在 CI 中进行限期对比#

设定一段时间,让 Bun 类型检查器与现有的必需检查并行运行。在收集运行时间和诊断结果期间,保留当前的发布判定机制。

除了故意加入错误的用例,还要观察日常开发中的变更。如果结果足以支持切换,就记录测得的收益和仍然存在的限制,并通过专门的拉取请求实施变更。

这样既方便作出采用决定,也方便在必要时回退。

此次发布还包含其他性能改进#

类型检查是主打功能,但所提供的发布概述还列出了 JSON.parse 提速、Node.js 兼容性修复,以及服务器空闲时 CPU 占用的降低。

据报告,空闲时 CPU 占用降低了 67%。这个数字也需要像类型检查器的基准测试一样谨慎看待。它是在特定测量条件下得到的结果,并不保证生产环境的整体 CPU 占用也会降低同样的幅度。

对于高负载服务,请求处理可能占据资源消耗的大部分。对于大部分时间处于空闲状态的服务,后台处理的占比可能更高。应在接近自身部署环境的条件下测试。

此次发布还引入了 Bun.FetchSession,并包含大量修复。所提供的概述没有足够的细节,无法据此评估该 API 的行为,或建议将其集成到项目中。采用前应查阅发布文档。

如果眼下的目标是加快类型检查,就先评估这一项变更。范围集中的试用,更容易解释结果。

用证据证明替换的价值#

Bun 1.4.3 提出了一个颇具吸引力的方案:大幅加快 TypeScript 类型检查、降低报告中的内存占用,并与 TypeScript 7.0.2 保持高度符合性。

剩下的问题是:在自己的仓库中,能否获得这些收益,同时又不产生对团队有实际影响的诊断结果差异?

先选择一个有代表性的项目。将 Bun 版本固定为 1.4.3,让其类型检查器与当前的 TypeScript 检查并行运行,并记录运行时间、峰值内存占用和所有不一致之处。再根据这些证据,判断是否应将 bun check 纳入开发工作流程的必需检查。

来源: https://www.publickey1.jp/blog/26/anthropicbuntypescript_73typescriptbun143.html

目录