2

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.

5
  • can you elaborate or provide a sample snippet to describe what you mean.. right now it is unclear.. Commented Apr 23, 2017 at 14:07
  • @suraj which part is unclear? Commented Apr 23, 2017 at 14:08
  • do you mean in typescript? Commented Apr 23, 2017 at 14:11
  • @suraj yea, angular2 is only typescript i think Commented Apr 23, 2017 at 14:12
  • 2
    technically it can be in ts,js or dart.. Commented Apr 23, 2017 at 14:14

1 Answer 1

6

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 }]
...
Sign up to request clarification or add additional context in comments.

8 Comments

It should be noted that this is not the same as an interface. For example, it introduces a value that can be instantiated at runtime. Not saying this is a bad solution, but use with caution. Also, implementing Foo as suggested in comments has a different meaning.
@AluanHaddad Question title differs from the real question, this was discussed in comments of a deleted answer. Since 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.
That will cause failure if they are inherited though. Do you mean for classes that are meant to be listed in an implements clause only? If so you should use private constructor() {throw Error('invalid');} that way you get a compiler check as well
Yes, either that, or as in the case above - if ConcreteFoo 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.
My pleasure. I decided to clarify the answer a bit, just in case if somebody will be confused by the title.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.