2
votes

Angular 2 & Typescript app.

I have an abstract class inside an NPM package that I am trying to provide implementation for inside my app code. This all worked fine until I added the public isLoggedIn:Subject<boolean>; property.

current-user.service.ts

@Injectable()
export abstract class CurrentUserContextService {

public isLoggedIn:Subject<boolean>;
public userId:string;
public userName:string;
public email:string;
public scope:string[];

constructor() {  }

}

my-current-user.service.ts

@Injectable()
export class MyCurrentUserContextService implements CurrentUserContextService {

// interface properties.
public isLoggedIn:Subject<boolean>;
public userId: string;
public userName: string;
public email: string;
public scope: string[];

// add custom properties as needed.


constructor() { }

}

// add custom methods as needed.

}

main.ts

bootstrap(AppComponent, [    
MyCurrentUserContextService,
{provide: CurrentUserContextService, useExisting: MyCurrentUserContextService}
])

Error

Class 'MyCurrentUserContextFactoryService' incorrectly implements interface 'CurrentUserContextFactoryService'. Types of property 'currentUserContext' are incompatible. Type 'MyCurrentUserContextService' is not assignable to type 'CurrentUserContextService'. Types of property 'isLoggedIn' are incompatible. Type 'Subject' is not assignable to type 'Subject'. Property 'destination' is protected but type 'Subject' is not a class derived from 'Subject'.

1
can you use extends instead of implements?Harry Ninh
Since this is a library, I need to force the dev using it to provide an implementation, extends would not enforce that. This example is simple, I have other classes that have methods that expect the developer to provide implementation.JBeckton
Hmm, because you are declaring base type as class, not interface, and implements should be using for interface only. So why don't you separate those you want the dev to implement to another interface, and keep those concrete base implementation in the current base class?Harry Ninh
The problem with using an interface is in Angular 2 DI you cannot inject an interface because at run time they do not exist. This technique, using a "class interface" is the solution. The abstract class is inject able and allows for the members to be overwritten with custom implementation.JBeckton

1 Answers

1
votes

I have discovered the root of my problem.... Angular CLI & Broccoli! After spending some time putting together some projects to reproduce this issue I decided to also use the Angular 2 quick start in addition to a CLI generated project.

No issues with the Angular 2 quick start project but the Angular CLI produces the errors without fail.

So by removing the CLI from my tool chain and writing my own tool code I can get reliable compilation of my TypeScript apps.