1

I have 2 services (1 abstract base service, 1 service extending this service), however for some reason I am getting this error:

core.js:3828 ERROR Error: This constructor is not compatible with Angular Dependency Injection because its dependency at index 5 of the parameter list is invalid.
This can happen if the dependency type is a primitive like a string or if an ancestor of this class is missing an Angular decorator.

Please check that 1) the type for the parameter at index 5 is correct and 2) the correct Angular decorators are defined for this class and its ancestors.
    at ɵɵinvalidFactoryDep (core.js:810)
    at Object.ConfigurationService_Factory [as factory] (ɵfac.js? [sm]:1)
    at R3Injector.push.../../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.R3Injector.hydrate (core.js:11347)
    at R3Injector.push.../../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.R3Injector.get (core.js:11170)
    at injectInjectorOnly (core.js:787)
    at ɵɵinject (core.js:792)
    at Object.MenuService_Factory [as factory] (ɵfac.js? [sm]:1)
    at R3Injector.push.../../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.R3Injector.hydrate (core.js:11347)
    at R3Injector.push.../../node_modules/@angular/core/__ivy_ngcc__/fesm5/core.js.R3Injector.get (core.js:11170)
    at injectInjectorOnly (core.js:787)

I tried following official Angular guide (https://angular.io/guide/ivy-compatibility-examples) to fix this issue when migrating to Angular 9 and IVY, but the problem still persists and I am really running out of ideas. This is my code:

Base service:

@Injectable()
export abstract class ConfigurationService implements 
IConfigurationService {
  abstract get angularHttp() : HttpClient;
  abstract get cordovaHttp() : HTTP;
  abstract get connectivityService() : IConnectivityService;
  abstract get data : ITest;
}

Derived class:

import { HTTP } from '@ionic-native/http/ngx';
import { HttpClient } from '@angular/common/http';
import { ConnectivityService } from './connectivity.service';

@Injectable()
export class ConfigurationService extends Core.ConfigurationService implements Core.IConfigurationService {

  constructor(
    public angularHttp : HTTPClient,
    public cordovaHttp : HTTP,
    public connectivityService : ConnectivityService,
    public data : ITest = data
  ) {
    super();
  }

}

Is it at all possible that Angular is somehow trying to "inject" into the base class and is throwing error? I am not really sure what to make of this..

Thanks for any ideas!

Edit (Solution) My bad - I have forgotten that my base class also takes in another argument which is just static data - configuration. In the end this is the problem.

The whole issue is that Angular will try and inject EVERYTHING in the BASE class. That means that it won't just try injecting Injectables, it will try to inject my static data as well which is, of course, wrong! I have adjusted the code to be like this:

Base service:

@Injectable()
export abstract class ConfigurationService implements 
IConfigurationService {
  abstract get angularHttp() : HttpClient;
  abstract get cordovaHttp() : HTTP;
  abstract get connectivityService() : IConnectivityService;
  abstract get data : ITest;
}

Derived class:

import { HTTP } from '@ionic-native/http/ngx';
import { HttpClient } from '@angular/common/http';
import { ConnectivityService } from './connectivity.service';
import { data } from './data';

@Injectable()
export class ConfigurationService extends Core.ConfigurationService implements Core.IConfigurationService {

  public data : ITest = data;

  constructor(
    public angularHttp : HTTPClient,
    public cordovaHttp : HTTP,
    public connectivityService : ConnectivityService,

  )

double-beep
  • 5,031
  • 17
  • 33
  • 41
Jiri Kralovec
  • 1,487
  • 1
  • 10
  • 18

2 Answers2

2

Try to add a constructor to your base class and pass the injected service from derived to base.

E.g.:

Base service:

@Injectable()
export class ParentService{
  constructor(private http:Http, private customService:CustomService){}
}

Derived service:

@Injectable()
export class ChildService extends ParentService{
  constructor (http:Http, customService:CustomService){
    super(http, customService);
  }
}

Edit:

Weirdly, abstract base components need to have a @Directive() decorator. At least mine were automatically "upgraded" that way anyway.

@Directive()
export abstract class FormStrategyDruidBase  {
  constructor(/* params here */) {
  }
}
zerocewl
  • 11,401
  • 6
  • 27
  • 53
  • Unfortunately, no luck there. Making it non-injectable does not work either + according to Angular's documentation, you SHOULD make it injectable (I added link in the original post) – Jiri Kralovec Mar 16 '20 at 08:48
  • How are you going to approach testing of Core library the abstract class comes from though? For example, an Core.XHRService would implement post/get/put/delete, and Child.XHRService would "fill" all the abstract implementations. Ideally, I would still like to test the Core service separately. – Jiri Kralovec Mar 16 '20 at 10:50
  • 1
    @zerocewl: I would like to give you +100! Adding @Directive() to the base component sorted this nasty issue for me! – CharithJ Feb 17 '21 at 22:03
-2

If nothing else works, add the following into the tsconfig.json

"angularCompilerOptions": { "enableIvy": false }

  • 4
    This is not a solution to the problem, it is downgrading away from the future of angular. Ivy is the new rendering engine and should be used - we need to fix our applications to support it, not just shut it off. – dudewad Jun 17 '21 at 02:48