带有针对 ES2022 的 Angular (15) 的 ClassDecorator

M's*_*ph' 6 decorator tsconfig angular-cli angular es2022

目前是 2023 年 3 月,我正在寻找一种方法让我的类装饰器以正确的方式工作,而不需要来自 cli 的警告。

这是我的简单代码:

function MyDecorator(myConstructor: new (...args: any[]) => any): new (...args: any[]) => any {
  alert('MyDecorator EVALUATE'); // -------------> Alert A
  return class extends myConstructor {
    constructor(...args) {
      super(...args);
      alert('MyDecorator CONSTRUCTOR'); // ------------> Alert B
    }
  };
}

@MyDecorator
@Component({
  // ...
})
export class AppComponent() {
  // ...
} 
Run Code Online (Sandbox Code Playgroud)

Angular 15 之前:

我的目标是 ES2021 或更低版本,这非常有效。我收到警报 A 和 B,但 cli 没有发出任何警告。

使用 Angular 15:

我的目标仍然是 ES2021,它仍然有效。我收到警报 A 和 B

cli 警告我它覆盖了一些设置。

TypeScript compiler options "target" and "useDefineForClassFields" are set to "ES2022" and "false" respectively by the Angular CLI. To control ECMA version and features use the Browerslist configuration. For more information, see https://angular.io/guide/build#configuring-browser-compatibility
Run Code Online (Sandbox Code Playgroud)

我尝试在中设置这两个设置tsconfig.json

TypeScript compiler options "target" and "useDefineForClassFields" are set to "ES2022" and "false" respectively by the Angular CLI. To control ECMA version and features use the Browerslist configuration. For more information, see https://angular.io/guide/build#configuring-browser-compatibility
Run Code Online (Sandbox Code Playgroud)

然后我没有更多的 cli 警告,但我只收到警报 A,并且我的装饰器实现明显被忽略(没有显示警报 B)。

看起来被"useDefineForClassFields": false忽略了(参见: https: //github.com/angular/angular/issues/48276#issuecomment-1362787912

嗯,我的两个问题是:

  • 有没有办法让装饰器在 Angular 15/ES2022 中“本地”工作?
  • 如果没有,有没有办法正确设置compilerOptionuseDefineForClassFields以避免cli的警告?

预先感谢您的任何帮助/解释...

Zze*_*Zze 4

“有没有办法让装饰器在 Angular 15/ES2022 中“本地”工作?”

从 Angular 15 开始,似乎无意支持应用于角度组件的自定义装饰器:

https://github.com/angular/angular/issues/48276#issuecomment-1332611012

Angular 不支持其组件类或其他装饰成员上的自定义装饰器。根据装饰器的作用,它可能会也可能不会正常工作。

我们不支持它们,因为存在很大的概念不匹配 - Angular 编译器试图根据其 Angular 注释静态转换类,但自定义装饰器试图在运行时任意更改该类的形状。


“如果没有,有没有办法正确设置 useDefineForClassFields compilerOption 以避免 cli 的警告?”

useDefineForClassFields我相信您收到此警告是因为它期望在定位 时使用默认值ES2022

https://angular.schule/blog/2022-11-use-define-for-class-fields

[当]TypeScript 的目标设置为 ES2022 时,此选项的默认值为true

这个标志实际上有什么作用?

这意味着将使用 JavaScript 的本机实现,并且属性的行为方式将与以前不同。根据设置,以下代码有两个不同的输出:

class User {
 age = this.currentYear - 1998;

 constructor(private currentYear: number) {
   // useDefineForClassFields: false --> Current age: 25
   // useDefineForClassFields: true --> Current age: NaN
   console.log('Current age:', this.age);
 }
}

const user = new User(2023);
Run Code Online (Sandbox Code Playgroud)