In my project, I have a class called Chart
that has various subclasses like BarChart
and TimeseriesChart
, all of which extend the base Chart
class.
To create these charts, I use a method named buildChart
. This method uses an enum called ChartsEnum
(examples include stackedTimeseries
and barChart
) to map the correct class using a Map:
export function buildChart(type: Charts, data: Array<TimeseriesData>) {
var chartsMap = new Map<Charts, InstantiableAbstractClass<typeof Chart>([
[Charts.stackedTimeseries, TimeseriesChart],
[Charts.barChart, BarChart],
])
const chart = chartsMap.get(type)
return new chart(data).chart;
}
The definition for the type InstantiableAbstractClass
is as follows:
export declare type InstantiableClass<T> = (new ( ...args: any) => { [x: string]: any }) & T;
For instance, the constructor of the TimeseriesChart
class looks like this:
export class TimeseriesChart extends Chart{
constructor(data: Array<TimeseriesData>) {
super(data);
}
}
Now, the goal is to add a new attribute called options
to the chart
class alongside the existing data
attribute. The issue arises because different types of options
are required for each ChartType (BarChart
, TimeseriesChart
). For example, BarChart
needs these properties:
{
start: number;
end?: number;
}
while TimeseriesChart
requires something like this:
{
description: string;
}
If we update the constructor of TimeseriesChart
with options, it would look like this:
export class TimeseriesChart extends Chart{
constructor(data: Array<TimeseriesData>, options: TimeseriesChartOptions) {
super(data, options);
}
}
This necessitates adding a new argument options
to the buildChart
method, which can then be passed to specific classes (similar to how we pass the data
argument).
What would be the best approach to handle this situation? One possibility could be utilizing generics and defining different types for options
based on the subclasses, but adjusting the InstantiableAbstractClass
type accordingly presents a challenge.
You can explore a complete example with additional explanations here.
Your guidance and insights are highly appreciated! Feel free to request more information if needed.
Thank you and best regards, Lukas