In an Angular 14 app, I have:
@Injectable()
export abstract class AbstractBaseService{
constructor(
protected override readonly serviceA: ServiceA,
protected override readonly serviceB: serviceB
) {
}
public abstract foo();
}
@Injectable()
export class ConcreteClass extends AbstractBaseService {
constructor(
protected override readonly serviceA: ServiceA,
protected override readonly serviceB: serviceB
) {
super(serviceA,serviceB,);
}
public foo(){
}
}
See the base class is declared as an abstract class, which means it cannot be instantiated directly. So should it have the Injectable() decorator?. If Yes, Why?
I removed @Injectable() from AbstractBaseService, and the app still works. Does this mean the decorator is optional? But LLMs are telling, that its ideal to have @Injectable()
for the base class also. Hence the confusion.
In an Angular 14 app, I have:
@Injectable()
export abstract class AbstractBaseService{
constructor(
protected override readonly serviceA: ServiceA,
protected override readonly serviceB: serviceB
) {
}
public abstract foo();
}
@Injectable()
export class ConcreteClass extends AbstractBaseService {
constructor(
protected override readonly serviceA: ServiceA,
protected override readonly serviceB: serviceB
) {
super(serviceA,serviceB,);
}
public foo(){
}
}
See the base class is declared as an abstract class, which means it cannot be instantiated directly. So should it have the Injectable() decorator?. If Yes, Why?
I removed @Injectable() from AbstractBaseService, and the app still works. Does this mean the decorator is optional? But LLMs are telling, that its ideal to have @Injectable()
for the base class also. Hence the confusion.
2 Answers
Reset to default 2try removing constructor from ConcreteClass
, this way constructor will be something like "inherited"
it won't work, and depending on the version of angular is used, you will either not be able to instantiate a class instance on the runtime, or you will receive a compile time error saying that Angular is unable to resolve DI params for constructor.
marking any class with any angular decorator makes angular compiler write down some metadata about the respective class' constructor, and it is the only way to make the DI constructor work, unless you are marking all of the parameters with direct @Inject(...) annotations.
I.e. in your case if you want to always call the base class constructor explicitly super(serviceA,serviceB);
marking base class with @Injectable() is not a necessity, but if you do, you'd be able to omit the child constructor
If your abstract class is using angular functionality, e.g: ViewChild
, @Input
, @Output
, etc. Then you need to add a decorator using the @Directive
decorator.
If not you can just declare the class as it is without either @Injectable
or @Directive
.
Because without the angular bells and whistles, it is just a javascript class so no decorator is needed.