When discussing a generic function, it should be understood that it operates based on the type parameter provided to it. However, in this particular scenario, the method determines its return type according to the enum parameter rather than the generic parameter. As a result, the method cannot be considered truly generic.
The reason for the compiler error is due to the fact that, as any T
derived from
AbstractPopup</code could be passed, there is no guarantee that the returned type will be compatible with the specific <code>T
being used in the function call. For example:
class OtherConcretePopup extends AbstractPopup{}
var p = popupFactory<OtherConcretePopup>(PopupType.ConcretePopup, {})
In this case, the code would technically be valid, but you are returning a ConcretePopup
even though the expected return type is OtherConcretePopup
.
A straightforward solution to this issue would be to create overloaded versions of the method for each different 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;
}
Alternatively, you could pass the constructor itself as an argument and eliminate the need for the switch statement entirely. This approach works best if all constructors have the same parameters and initialization process:
function popupFactory<T extends AbstractPopup>(popupType: new() => T, data: {}): T
{
var popup = new popupType();
return popup;
}
var p = popupFactory(ConcretePopup, {})