Skip to content

ngOnDestroy not allowed on non decorated classes used with useClass or useFactory #50462

@Harpush

Description

@Harpush

Which @angular/* package(s) are the source of the bug?

core

Is this a regression?

No

Description

Angular requires every class using OnDestroy interface to be decorated with @Injectable. That actually makes it impossible to use useClass or useFactory together with OnDestroy when there is a dependency which isn't a class.
An example:

export class Test implements OnDestroy {
  constructor(private readonly num: number) {
    console.log(this.num);
  }
  
  ngOnDestroy(): void {
    console.log('Test Removed!');
  }
}

export function createTest(num: number): [InjectionToken<Test>, Provider] {
  const token = new InjectionToken<Test>('Test');
  const numToken = new InjectionToken<number>('num');

  const numProvider: Provider = {
    provide: numToken,
    useValue: num,
  };

  const provider: Provider = {
    provide: token,
    useClass: Test,
    deps: [numToken],
  };

  return [token, [numProvider, provider]];
}

This code will run and work. You can also see there was once a PR that allowed destroy on factory created classes: #23755.

The problem here is there is an error loop. OnDestroy won't compile here unless I add @Injectable but then I can't use useClass with the number dep as it is not known at compile time (Due to strictInjectionParameters).
I don't think turning off strictInjectionParameters is a good option as it has benefits in other cases. The better idea is allowing OnDestroy on all classes regardless of them being decorated or not especially as the runtime allows it.

Please provide a link to a minimal reproduction of the bug

No response

Please provide the exception or error you saw

Class is using Angular features but is not decorated. Please add an explicit Angular decorator.(-992007)

Please provide the environment you discovered this bug in (run ng version)

Angular 16.0.0

Anything else?

Stackblitz won't reproduce the error only in a real project hence no reproduction (strictInjectionParameters has no effect there).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions