Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Class decorator stopped working on angular@15 #48276

Closed
naturalfreak opened this issue Nov 29, 2022 · 7 comments
Closed

Class decorator stopped working on angular@15 #48276

naturalfreak opened this issue Nov 29, 2022 · 7 comments

Comments

@naturalfreak
Copy link

naturalfreak commented Nov 29, 2022

Having class decorator:

export function openDialogClass() {
  return function <T extends { new(...args: any[]): {} }>(constructor: T) {
    return class extends constructor {
      mat_dialog = inject(MatDialog);
    };
  }
}

And in component:

@Component({
  selector: 'page',
  templateUrl: 'index.html',
  styleUrls: ['style.scss'],
})

@openDialogClass()
export class Component{ 
    constructor(){
       consol.log(this.mat_dialog) // On angular@14 it's fine, but on angular@15 it's undefined
   }
}
Angular CLI: 15.0.1
Node: 18.12.1
Package Manager: npm 8.19.2
OS: linux x64

Angular: 15.0.1
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... platform-server, router, service-worker

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1500.1
@angular-devkit/build-angular   15.0.1
@angular-devkit/core            15.0.1
@angular-devkit/schematics      15.0.1
@angular/cdk                    15.0.0
@angular/material               15.0.0
@schematics/angular             15.0.1
rxjs                            7.5.7
typescript                      4.8.4
@JeanMeche
Copy link
Member

Could you provide a working exemple ? I'm also getting undefined on 14.2.

@naturalfreak
Copy link
Author

Here is a working example:
testdecorator.zip

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

@classDecorator()
export class AppComponent {
  title = 'testdecorator';

  constructor(){
  }

  ngOnInit(){
    console.log((this as any).api_provider); //THIS IS 'test'
  }

}

export function classDecorator() {
  return function <T extends { new(...args: any[]): {} }>(constructor: T) {
    return class extends constructor {
      api_provider = "test"
    };
  }
}

@JeanMeche
Copy link
Member

JeanMeche commented Nov 29, 2022

It works on v15 in here

@alxhub
Copy link
Member

alxhub commented Nov 30, 2022

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.

@jogelin
Copy link

jogelin commented Dec 22, 2022

@alxhub Do you have some documentation or something that indicates that we cannot use custom decorators in Angular and why?

We are meeting the same situation here with a decorator UntilDestroy() that makes the ContentChild not selecting, not recognizing our MatFormFieldControl anymore even if the decorator is empty. I would like to understand why...

@jogelin
Copy link

jogelin commented Dec 22, 2022

After some research, this is related to a modification of the way properties are set as you can see in the Typescript documentation. This new way is applied when your target is es2022.

Angular cli is aware of this as you can this in this code , it will set the correct value

The solution then is to set the target to es2021 then Angular Cli will hook the configurations and set es2022 and useDefineForClassFields to false

There is only one thing that we still don't understand is that if you set these values yourself to avoid the warning of Angular Cli, then it doesn't work. It seems typescript will read directly the file and just ignore useDefineForClassFields

Related tickets:
microsoft/TypeScript#45995
microsoft/TypeScript#48814
angular/angular-cli#24435

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jan 22, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants