TypeScript 中的实验性装饰器:深入剖析其内部机制

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

为什么你的 TypeScript 会报“实验性装饰器”警告?

\n\n

你是否曾经在编译 TypeScript 项目时,在控制台中看到过类似这样的信息:

\n\n
Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig.json' or '--experimentalDecorators' to remove this warning.
\n\n

如果是的话,你并不孤单。这个问题在 Stack Overflow 上获得了数千次浏览和数十个回答。但大多数回答只是建议“勾选选项然后忘掉它”。而今天,我们将更进一步:深入了解什么是 TypeScript 中的实验性装饰器警告,它从何而来,内部是如何工作的,以及为什么 TypeScript 会将装饰器视为“实验性”的。

\n\n

什么是 TypeScript 中的装饰器(以及为什么它们是实验性的)?

\n\n

装饰器是一种强大的元编程工具。它们允许你在运行时对类、方法、属性和参数进行注解和修改。如果你使用过 Angular、NestJS 或 TypeORM,你肯定已经遇到过它们:

\n\n
@Component({\n  selector: 'app-root',\n  templateUrl: './app.component.html'\n})\nclass AppComponent {}
\n\n

但问题在于:JavaScript 的装饰器标准(TC39 提案)目前仍处于 Stage 3 阶段。这意味着其语法和语义可能会发生变化。TypeScript 作为 JavaScript 的超集,不能简单地“冻结”实现——它通过 experimentalDecorators 标志提供了 装饰器的实验性支持。

\n\n

当你启用此选项时,TypeScript 编译器会生成可能在未来标准更新时过时或失效的代码。正是因为这个原因,它诚实地警告你:“使用风险自负”。

\n\n

实验性装饰器警告在编译器内部是如何工作的?

\n\n

为了理解这个警告,让我们看看 TypeScript 的源代码。在 checker.ts 文件(是的,这是编译器内部的一个真实文件)中,有一个名为 checkGrammarForDecorator 的函数。当解析器遇到装饰器时,编译器会检查 tsconfig.json 中是否设置了 experimentalDecorators 标志。

\n\n

如果该标志未设置,它就会生成一条诊断信息——也就是你看到的那个警告。它不是一个错误(代码仍然可以编译),但编译器会反复提醒你:“嘿,你正在使用一个可能会改变的功能!”。

\n\n

简化后的逻辑如下所示:

\n\n
// TypeScript 实际逻辑的伪代码\nfunction checkDecoratorUsage(decorator: Decorator, options: CompilerOptions) {\n  if (!options.experimentalDecorators) {\n    reportDiagnostic({\n      code: 1219,\n      message: "Experimental support for decorators is a feature that is subject to change in a future release..."\n    });\n  }\n}
\n\n

错误代码 1219 正是你看到的那个警告。而代码 1220 则是针对 emitDecoratorMetadata 的类似警告(这是另一个实验性标志,我们稍后会讨论)。

\n\n

如何关闭实验性装饰器警告:3 种方法

\n\n

最简单的方法是在 tsconfig.json 中添加标志:

\n\n
{\n  "compilerOptions": {\n    "experimentalDecorators": true\n  }\n}
\n\n

如果你使用命令行:

\n\n
tsc --experimentalDecorators
\n\n

或者,如果你没有 tsconfig.json,可以直接传递标志:

\n\n
npx tsc --experimentalDecorators src/index.ts
\n\n

之后,警告就会消失。但这只是冰山一角。让我们深入了解当你启用 experimentalDecorators 时实际发生了什么。

\n\n

编译器在底层生成了什么?

\n\n

当你编写一个类装饰器

博客

书籍推荐