OC

Knowledge OS
把 Go 的 defer 搬进 TypeScript:语法能复制,错误模型复制不了
科技 · 2026-08-03 · 开发者工具 · 阅读 0

把 Go 的 defer 搬进 TypeScript:语法能复制,错误模型复制不了

作者:林岚|OC 开发者生态编辑

作者:林岚|OC 开发者生态编辑

开发者 Andrew Healey 修改 TypeScript 编译器,给语言加入类似 Go 的 defer 语句,并记录了从解析器、类型检查到 JavaScript 转换的完整过程。实验文章最后得出的结论却是:实现之后,他反而不打算把这项语法带进生产项目。

一句话结论:defer 的后进先出清理很容易解释,难的是 JavaScript 已有异常、异步和资源管理语义;复制一个关键词,必须同时决定多次失败时到底保留哪个错误。

实验实现会在执行到 defer 时立刻捕获函数、接收者和参数,再把调用压入当前作用域的清理栈。控制流走到哪里,就登记哪些清理动作;离开作用域时按后进先出顺序执行。这样能自然表达“打开后关闭”“加锁后解锁”等成对操作。

编译器改动并不只是在解析器里认出新词。TypeScript 需要新的 AST 节点、语法检查、类型检查和转换逻辑,还要确保不同退出路径都执行清理。异步版本更复杂:多个清理任务是串行等待还是并行,清理失败是否继续,都会改变程序行为。

函数体错误与多个清理错误需要明确合并而不能静默覆盖

作者选择保留函数体原始错误,同时继续执行全部清理,并把清理失败汇总进 AggregateError。这是一种合理政策,却不是 Go 或现有 JavaScript 自动给出的答案。若最后一个清理错误覆盖业务错误,调试信息会丢失;若遇到第一个错误就停止,后面的资源又可能泄漏。

TypeScript 其实已经支持 JavaScript 的显式资源管理:usingawait using 会调用对象的 Symbol.disposeSymbol.asyncDispose,并通过 SuppressedError 处理主体与清理同时失败。它比任意函数 defer 更受约束,但也因此更容易形成统一协议和库生态。

这次实验最有价值的不是新语法,而是暴露隐藏设计。一个看似简单的便利功能会把作用域、闭包捕获、异常优先级和异步顺序全部拉进语言规范。问题不在能不能做,而在团队是否愿意长期维护另一套清理语义。

关键事实

  • 实验内容:修改 TypeScript 解析器、AST、检查器和转换器以支持 defer
  • 执行语义:登记时捕获调用信息,离开作用域时后进先出执行
  • 错误策略:保留主体错误,继续清理并聚合清理阶段失败
  • 现有替代:TypeScript 已支持 usingawait using 和显式资源管理协议

OC 判断

语法糖只有在全语言错误模型里才是甜的。对 TypeScript 来说,优先使用标准 using 协议比维护私有编译器分支可靠;确实需要任意延迟调用时,普通 try/finally 虽然啰嗦,却不会制造新的语言方言。

为什么重要

  • 对开发者:清理代码要先定义错误优先级和异步顺序,不能只追求写法简短。
  • 对库作者:实现标准 dispose 协议,可以让资源进入统一的 using 工作流。
  • 对团队:私有语法会增加工具链、编辑器、构建和新成员学习成本。

参考来源

相关阅读

基于标题、摘要和正文内容自动匹配。

更多科技

评论

围绕这篇文章补充信息、提出问题或分享观察。

0
暂无评论。

发表评论