My experience (coming from java backend development) into frontend dev is the following.
If we speak about 'interface' I have the strong expectation that an main principle of using interface is assured by languages who 'offer' interface.
Which is: 'code against interface not against implementation'.
This seems to not be assured by typescript/angular2. (than they shouldn't use word interface yet, maybe).
What was my case (warning: I'm learning angular2 so my workaround could seem ugly to advanced users):
Component A1 has a child component B.
Component B should know the parent and call a method on parent.
So component B receives the parent via DependencyInjection in it's constructor.
constructor( private a: A1Component) {}
Everything is fine.
Than things get complicated.
Another component A2 can be the parent of comp. B.
Ideally I should inject in B an interface (not implementation) which is implemented by both A1 and A2 (this would be naturally in java world).
Than B would work with this interface. If needed, A typecast to A2 for example would make B aware if the instance he has is really A2 or not.
I speak about plain components/classes, not services (I see that most solutions refers to services).
I tried to use @Host(), @Injectable(), OpaqueToken, Providers but always there was an error. When in the end it seemed to work: in reality the object injected in Component B was an empty object, not the parent - maybe I wrongly used to providers and a new empty object was created instead of injecting the parent object.
What I did in the end: I didn't use interface.
I created a plain base class for A1 and A2 - let's call it ABase.
Component B would keep a reference to this base class. Reference would be set in constructor as this:
//BComponent:
parent: ABase;
constructor(@Optional parentA1: A1Component, @Optional parentA2: A2Component) {
if( parentA1 )
this.parent = parentA1;
else
this.parent = parentA2
}
Yes, it's a strange workaround, not nice (coming from java world thinking, I agree) - but I just run out of time and was disappointed about the 'interface' thing.
Updated
I reconsider the previous answer (it's bad design, ugly ... was at the my beginnings with angular)
Now Angular's documentation have clear description on this exact issue: finding the parent of a component.
Can not use interface - as interface can not be injected.
"Looking for components that implement an interface would be better. That's not possible because TypeScript interfaces disappear from the transpiled JavaScript, which doesn't support interfaces. There's no artifact to look for."
Can not use base class of possible parents neither ... (this is the root cause of my with previous desperate, bad- answer)
What works? Technique: find a parent by its class-interface.
Mainly:
Child B see a general parent Parent
(can be A1Component or A2Component)
export class BComponent {
name = 'B';
constructor( @Optional() public parent: Parent ) { }
}
And the each possible parent component provides a Parent
(at component level !!!) using class-interface:
providers: [{ provide: Parent, useExisting: forwardRef(() => A1Component) }],
providers
to something likeproviders: [{ provide: APP_CONFIG, useClass: AppConfigMockClass }]
– Curiosity