SemperCallide SemperCallide - 2 months ago 9
TypeScript Question

How can you return a dynamically typed object in Typescript / Angular2?

I am trying to create a modal generator service. Ultimately, I would like to use it to creative various types of modals.

I have a function to create modal components, and I would like it to accept various types of modal components as input, and return a ComponentRef< (modaltype) > as output. The problem is that I am having some trouble with the syntax.

The problem, specifically, is the function declaration. This is what it looks like right now:

private createModalComponent (compType : Type<Component>, vCref: ViewContainerRef): ComponentRef<compType> { ... }


This is giving me the error that "cannot find name 'compType'", which makes sense. So I also tried a more generic approach:

private createModalComponent<T> (compType : T, vCref: ViewContainerRef): ComponentRef<T> { ... }


But that gave me the error that "Argument of type 'T' is not assignable to parameter of type 'Type<{}>'.

So I'm stumped. How does one go about returning a dynamically typed object in typescript?

import { Injectable, ViewChild, ViewContainerRef, ElementRef,
EventEmitter, OnInit, ComponentRef, ComponentFactoryResolver,
Type, ReflectiveInjector } from '@angular/core';
import { WizardModalComponent } from './wizard-modal/wizard-modal.component'


@Injectable()
export class ModalGeneratorService {

constructor(private _cmpFctryRslvr: ComponentFactoryResolver, private _vcRef: ViewContainerRef) {}

private createModalComponent (compType : Type<Component>, vCref: ViewContainerRef): ComponentRef<compType> {
let factory = this._cmpFctryRslvr.resolveComponentFactory(compType);
// vCref is needed cause of that injector..
let injector = ReflectiveInjector.fromResolvedProviders([], vCref.parentInjector);
// create component without adding it directly to the DOM
let comp = factory.create(injector);
return comp;
}

createWizardModalcomponent(vCref : ViewContainerRef) {
createModalComponent(WizardModalComponent, vCref);
}
}

Answer Source

Thank you everyone who commented or answered, I found an answer that works exactly the way I want and it is very simple.

I simply use the 'any' type in place of the component type for component ref, like so:

private createModalComponent (compType : Type<Component>, vCref: ViewContainerRef): ComponentRef<any> { ... }

At times like these, it always helps to remember that, although Typescript generally uses static typing, it is merciful enough to grant us the 'any' keyword. Hope someone else finds this useful.