在 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,你可以操作信息,存储每个变量被引用的作用域,并检查是否有人试图从另一个作用域访问它(这是一个简短的版本)。
