A generic function implies it should work based on the generic type parameter passed to it. In your case the method decides the return type based on the enum parameter, not based on the generic parameter. So the method is not really generic.
The reason the compiler complains is that, since you could pass any T derived from AbstractPopup it can't really check that the type you return will be compatible with the specific T you pass to the function. Consider the following valid code:
class OtherConcretePopup extends AbstractPopup{}
var p = popupFactory<OtherConcretePopup>(PopupType.ConcretePopup, {})
The code would be valid, but you return a ConcretePopup even though the return type is OtherConcretePopup
The simplest solution would be to have several overloads to the method for each popup type:
function popupFactory(popupType: PopupType.OtherConcretePopup, data: {}): OtherConcretePopup
function popupFactory(popupType: PopupType.ConcretePopup, data: {}): ConcretePopup
function popupFactory(popupType: PopupType, data: {}): AbstractPopup
{
var popup: AbstractPopup = null;
switch (popupType)
{
case PopupType.ConcretePopup:
{
popup = new ConcretePopup();
break;
}
}
return popup;
}
Or you could pass the constructor as a parameter and eliminate the need for the switch altogether, but this a good option only if all the constructors have the same number of parameters and the initialization is the same for all:
function popupFactory<T extends AbstractPopup>(popupType: new() => T, data: {}): T
{
var popup = new popupType();
return popup;
}
var p = popupFactory(ConcretePopup, {})