网站搜索

在 TypeScript 中有可能防止闭包捕获外部变量吗?


假设我有以下 Typescript 代码:

const x = 123
const f = () => x 

是否有可能做一些事情,以便 Typescript 编译器在编译时产生错误/警告,提示函数 f 正在捕获外部变量 x?

附言:我只是单纯地寻找此机制的技术可行性,关于为什么我不应该这样做的解释将不被接受为答案。

答案#1

采纳了尤金的建议,我写了一个 eslint 插件来实现这一点。如果你安装并配置该插件,以下代码:

const x = 123
// eslint-no-closure
const f = () => x 

将生成:

file.ts
  1:7   error  declared variable x referenced in an `eslint-no-closure` function  no-closure/no-tagged-closures
  3:11  error  function tagged with `eslint-no-closure` closes variables: x       no-closure/no-tagged-closures
  3:17  error  reference to variable x in an `eslint-no-closure` function         no-closure/no-tagged-closures

✖ 3 problems (3 errors, 0 warnings)

默认的报告有点冗长,但可以精简。

答案#2

你正在寻找的不是编译器的某些配置,而是代码审查工具的配置。

参见 ESLint,例如以及像 no-shadow 这样的规则:

遮蔽是指局部变量与其所在作用域中的变量同名的过程。此规则旨在消除被遮蔽的变量声明。

之所以它不在编译器基础设施中——责任太大。编译器负责解析源代码并生成有意义的目标代码,这不是一件容易的事。检查可读性、强制最佳实践等对它来说负担太重。这就是为什么会有像 lint 工具这样的工具,它在你的代码中强制规则,从而推动可读性实践等。

更新:我理解错了问题,楼主关注的不是变量遮蔽,而是使用上层作用域的变量。

我想到实现这一点的方法是为 linter 编写你自己的插件,它将实现这种行为。

例如,你可以为 ESLint 实现你自己的规则——参考开发者指南。

所以这个想法是你实现你自己的规则(函数),它必须返回一个用于 AST 节点的访问者。通过访问代码的 AST,你可以操作信息,存储每个变量被引用的作用域,并检查是否有人试图从另一个作用域访问它(这是一个简短的版本)。