I want to write a feature module that consumes a service. This feature module should not be concerned with the implementation of this service, but rather expect that it implement an interface and that's it.
Caveat: The interface that the service should implement will not be defined by this module.
Corollary: Where should this interface be defined?
The feature module is meant to be used in many applications across our organization. Each is able to implement the interface for the required service in a different way. If a new use case presents itself, the interface may change and prompt changes to the feature module.
The design that we settled on placed this interface into a shared library.
This article shows that using an InjectionToken
causes the following error 'NullInjectorError: No provider for InjectionToken ...`
I've created a StackBlitz example that illustrates the above setup and issue.
The above thoughtram article describes how OpaqueToken
was designed to prevent accidental collision of these strings. Adding that, later InjectionToken
wrapped the OpaqueToken
to add additional typescript support.
I would like the typescript support for me and my team, but with a token that allows controlled collision.
See this StackBlitz Controlled Collision Token
The above example can be fixed if the InjectionToken
is replaced with a string.
Change the following two (identical files) as such
export const I_SHARED_SERVICE = new InjectionToken<ISharedService>('i-shared-service.shared');
=>
export const I_SHARED_SERVICE = 'i-shared-service.shared';
The result is a loss of typescript support. This seems like a step backwards.
It takes a village to raise a child or to come up with a good architecture.
After discussion with my coworker I've realized that an interface module (a separate npm package) solves the problem.
The result is that I've got my consuming projects, my feature project and the interface project.
consuming project: provides adapter between feature module and internal consumer, providing interface project's InjectionToken
.
feature project: provides feature components and consumes interface project's InjectionToken
.
interface project provides interfaces corresponding InjectionToken
s