My application displays data about different kinds of business objects in the same standard component.
That is, let's assume there is an Angular component type EditorComponent<T extends object>
.
This component is instantiated using a component outlet that receives a custom injector initialized with providers that are specified to each business object type in an interface like this:
interface IBusinessObjectInfo {
readonly providers?: StaticProvider[]
}
The concrete business object types are supplied by individual business modules (that the framework must not know about). Thus, for each business object type, something like this is done:
boInfo: IBusinessObjectInfo = createBusinessObjectInfo({
objectRestrictions: { ... },
...
});
where createBusinessObjectInfo
accepts an interface like this:
interface ITypedBusinessObjectInfo<T extends object> {
readonly objectRestrictions: IObjectRestrictions<T>;
...
}
That is, the object passed to createBusinessObjectInfo
is generically typed to the business object type.
Now, it's the responsibility of the createBusinessObjectInfo
function to generate providers based on the supplied object info that are equipped with appropriately typed injection tokens.
Within EditorComponent<T>
, then, I want to inject those objects, and also instantiate some other classes from the framework that work on business objects and are generically typed to them. For example:
@Component...
class EditorComponent<T extends object> {
public constructor() {
this.restrictionViewModel = new RestrictionViewModel<T>(this.objectRestrictions);
}
public readonly restrictionViewModel: RestrictionViewModel<T>;
private readonly objectRestrictions: IObjectRestrictions<T> = inject(...);
}
So far, so good.
The question is: Where/how do I get my generically typed injection tokens from?
I could define them without any typing:
export const objectRestrictionToken = new InjectionToken('object restrictions');
Then, I could cast them upon use, or - slightly more convenient to write - hand them out only using a function:
export function getObjectRestrictionToken<T extends object>(): InjectionToken<IObjectRestrictions<T>> {
return <InjectionToken<IObjectRestrictions<T>>>objectRestrictionToken;
}
Obviously, this solution with an explicit typecast of an existing object instance is not so nice. Nor is it nice that I have to explicitly specify T
when calling the getObjectRestrictionToken<T>
function.
Is there any other way, without damaging the separation between (generic) framework and concrete business modules?