Angular library module inject service with abstract class

I think there should be 'useValue' instead of 'useClass'.

export class ComponentsModule {
  static forRoot(pageService): ModuleWithProviders {
    return {
      ngModule: ComponentsModule,
      providers: [
        {provide: 'PageService', useClass: pageService}
      ]
    };
  }
}

As Sunil Singh said, a normal abstract class is the solution (without @Injectable).

export abstract class AbstractPageService {

  abstract logout(): void;

}

To reuse singleton

Provide in application appModule.ts

{ provide: 'currentCompanyService', useFactory: getCompanyServiceFactory, deps: [AppInitService]}

Create factory which just returns injected instance.

export function getCompanyServiceFactory(appInitService: AppInitService): AppInitService {
 return appInitService;
}

Inject in library component

public CustomLibraryComponent {

   private companyService: AppInitService;

   constructor(@Inject('currentEnvironment') environment: any,
               @Inject('currentCompanyService') companyService: AppInitService) {
       this.environment = environment;
       this.companyService = companyService;
   }
}

I used this approach but ran into one problem:

The PageService is not the same singleton instance in the library as in the application. Because it is provided in multiple modules (application module and the library module), it creates a new instance for each module.

What I ended up doing was providing my service through a string in the application module:

// app.module.ts in the root application
providers: [
  {
    provide: 'PageService',
    useClass: PageService
  }
]

Then injecting the service where needed using @Inject()

// anywhere in the root application where the service is needed
constructor(@Inject('PageService') private pageService: PageService) {}

Then, in the library, I created a simple interface:

export interface AbstractPageService {
  logout(): void;
}

Then, I can simply inject the service in the library through the Inject() decorator and type it using the interface (without the need to implement the interface in the root application):

// anywhere in the library where the service is needed
constructor(@Inject('PageService') private pageService: AbstractPageService) {}

Now both the root application and the library use the same singleton instance of the PageService, as provided in the root application.