Is there a way to export a class as interface and then import that interface in another module in Angular 2? I need to be able to inject the class in a constructor in some components e.g should be registered as provider.
-
can you elaborate or provide a sample snippet to describe what you mean.. right now it is unclear..Suraj Rao– Suraj Rao2017-04-23 14:07:20 +00:00Commented Apr 23, 2017 at 14:07
-
@suraj which part is unclear?Christo S. Christov– Christo S. Christov2017-04-23 14:08:46 +00:00Commented Apr 23, 2017 at 14:08
-
do you mean in typescript?Suraj Rao– Suraj Rao2017-04-23 14:11:26 +00:00Commented Apr 23, 2017 at 14:11
-
@suraj yea, angular2 is only typescript i thinkChristo S. Christov– Christo S. Christov2017-04-23 14:12:57 +00:00Commented Apr 23, 2017 at 14:12
-
2technically it can be in ts,js or dart..Suraj Rao– Suraj Rao2017-04-23 14:14:04 +00:00Commented Apr 23, 2017 at 14:14
1 Answer
In order to be used as both an interface and provider token, it may be abstract class. This is how it is done in Angular code base itself.
If concrete class has something to inherit from abstract class, the latter can be extendable:
export abstract class Foo {
abstract bar();
baz() { ... }
}
export class ConcreteFoo extends Foo {
bar() { ... }
}
...
provider: [{ provide: Foo, useClass: ConcreteFoo }]
...
Otherwise it's safer to make abstract class non-extendable and non-instantiatable:
export abstract class Foo {
private constructor() {
throw new Error('should not be instantiated directly');
}
abstract bar();
}
export class ConcreteFoo implements Foo {
bar() { ... }
}
It should be noticed that any class can be used as an interface in TypeScript. So if there's no real need to differentiate between interface and implementation, it may be just one concrete class:
export class Foo {
bar() { ... }
baz() { ... }
}
...
provider: [Foo]
...
Which may be used later as an interface if necessary:
export class SomeFoo implements Foo { ... }
...
provider: [{ provide: Foo, useClass: SomeFoo }]
...
8 Comments
Foo as suggested in comments has a different meaning.Foo is supposed to be a provider, yes, it will obviously exist in transpiled JS code. When abstract class is used only as an interface (e.g. const foo: Foo = ... and ... implements Foo ...), it won't be transpiled - this is done frequently in Angular source code, too.implements clause only? If so you should use private constructor() {throw Error('invalid');} that way you get a compiler check as wellConcreteFoo has nothing to inherit from Foo, Foo may throw in its constructor, so a dev won't get noop service by chance with provide: [Foo]. Thanks for reminding about private constructor, that's a good one.