ClassDecorator with Angular (15) targeting ES2022

huangapple go评论65阅读模式
英文:

ClassDecorator with Angular (15) targeting ES2022

问题

在2023年3月,我正在寻找一种方法来使我的类装饰器在Angular 15 / ES2022中正常工作,而不会收到来自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() {
  // ...
} 

在Angular 15之前:

我以ES2021或更低的目标进行开发,这完全正常工作。我收到了警告A和B,CLI没有警告。

使用Angular 15:

我仍然以ES2021为目标,并且仍然正常工作。我收到了警告A和B

但是 CLI警告我覆盖了一些设置。

Angular CLI将TypeScript编译器选项“target”和“useDefineForClassFields”分别设置为“ES2022”和“false”。要控制ECMA版本和功能,请使用Browerslist配置。有关更多信息,请参见https://angular.io/guide/build#configuring-browser-compatibility

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

    "target": "ES2022",
    "useDefineForClassFields": false,

然后CLI不再警告,但是我只收到警告A,我的装饰器实现明显被忽略了(没有显示警告B)。

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

我的两个问题是:

  • 有没有办法使装饰器在Angular 15/ES2022中“原生”工作?
  • 如果不行,有没有办法正确设置useDefineForClassFields编译选项以避免CLI的警告?

非常感谢任何帮助/解释...

英文:

We currently are in march 2023 and I am looking for a way to make my class decorators work the right way, with no warning from the cli.

Here my simple code :

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() {
  // ...
} 

Before Angular 15:

I was targeting ES2021 or lower and this worked perfectly. I got alerts A & B and the cli gave no warning.

With Angular 15:

I was still targeting ES2021 and it was still working. I got alerts A & B

BUT the cli warned me it overrided some settings.

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

I tried to set these two settings in the tsconfig.json

    "target": "ES2022",
    "useDefineForClassFields": false,

Then I had no more cli warning BUT I only got the alert A and my decorator implementation is clearly ignored (no alert B was displayed).

It looks like that the "useDefineForClassFields": false is ignored (cf : https://github.com/angular/angular/issues/48276#issuecomment-1362787912)

Well my 2 questions are :

  • is there a way to make decorators work "natively" in Angular 15/ES2022 ?
  • if not, is there a way to properly set the useDefineForClassFields compilerOption to avoid the warning of the cli ?

Thanks in advance for any help/explanation ...

答案1

得分: 4

没有办法在 Angular 15/ES2022 中使装饰器在组件上“本地”地工作。从 Angular 15 开始,不再支持自定义装饰器应用于 Angular 组件:

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

> Angular 不支持在其组件类或其他已装饰成员上使用自定义装饰器。根据装饰器的功能,它可能无法正常工作。我们不支持它们是因为存在重大概念不匹配 - Angular 编译器试图根据其 Angular 注解静态转换类,但自定义装饰器试图在运行时任意更改类的形状。


如果不能,有没有一种方法可以正确设置 useDefineForClassFields 编译器选项,以避免 CLI 的警告?

我认为你收到此警告是因为它希望在目标为 ES2022 时使用 useDefineForClassFields 的默认值。

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

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

这个标志实际上是做什么用的?

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

> typescript > class User { > age = this.currentYear - 1998; > > constructor(private currentYear: number) { > // useDefineForClassFields: false --> 当前年龄:25 > // useDefineForClassFields: true --> 当前年龄:NaN > console.log('当前年龄:', this.age); > } > } > > const user = new User(2023); >

英文:

"is there a way to make decorators work "natively" in Angular 15/ES2022 ?
"

It appears that there is no intention of supporting custom decorators applied to angular components from Angular 15 onwards:

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

> Angular doesn't support custom decorators on its component classes or other decorated members. Depending on what the decorator does, it may or may not function correctly.

> We don't support them because there's a big conceptual mismatch - the Angular compiler is trying to statically transform classes according to their Angular annotations, but custom decorators are attempting to arbitrarily change the shape of that class at runtime.


"if not, is there a way to properly set the useDefineForClassFields compilerOption to avoid the warning of the cli ?"

I believe you are getting this warning because it is expecting the default value to be used for useDefineForClassFields when targeting ES2022.

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

> [When] the target of TypeScript is set to ES2022, the default value for this option is true.

What does this flag actually do ?

> This means that the native implementation of JavaScript will be used and that the properties will behave in a different way than before. Depending on the setting, the following code has two different outputs:

> 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);

huangapple
  • 本文由 发表于 2023年3月9日 19:07:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75683757.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定