I'm writing some graphing code in TypeScript 2.6, and I'm have a small obstacle with respect to inheritance and generic code:
abstract class Series { /**/ }
class LineSeries extends Series { /**/ }
class BarSeries extends Series { /**/ }
class ScatterSeries extends Series { /**/ }
class Chart {
private seriesArray: Series[] = [];
constructor(series: Series[]) {
let seriesType: typeof Series = null;
switch (series.SeriesType) {
case SeriesType.LineSeries:
seriesType = LineSeries;
break;
case SeriesType.BarSeries:
seriesType = BarSeries;
break;
case SeriesType.ScatterSeries:
seriesType = ScatterSeries;
break;
default:
throw "Unsupported series type";
}
for (let i = 0; i < series.length; i++)
this.SeriesArray.push(new seriesType());
}
}
I intended the code above to construct a new object that is derived from Series
, where the constructor on the last line comes from a runtime-assigned type value. The problem I have is that Series
is abstract, so I cannot instantiate it, however I will never assign the value typeof Series
to the series
variable. (But TypeScript doesn't know that).
I have thought of a few solutions, but none of them are especially elegant. One is to simply remove the abstract
modifier from Series
and optionally put in some code to throw an exception if it's instantiated. Another solution is to change the definition of seriesType
to:
let seriesType: (typeof LineSeries | typeof BarSeries | typeof ScatterSeries) = null;
but then I need to maintain this list every time I add a new type of series. I know I can do, for example:
type DerivedSeries = (typeof LineSeries | typeof BarSeries | typeof ScatterSeries);
and then
let seriesType: DerivedSeries = null;
but this is not much of an improvement, if at all.
Is there any more elegant way I can tell TypeScript that seriesType
is of type Series
, but must also be of an instantiable child type? i.e. the expression seriesType = Series;
should throw a compile-time error, not new seriesType();
.
Thanks
The simplest way to instantiate classes derived from an abstract class is by defining an object type with the
new()
method: