I am relatively new to using TypeScript and am currently working on a project that involves handling various shapes of data from different sources. My goal is to pass this data to different aggregator classes, with one aggregator class corresponding to each specific data shape.
In order to achieve this, I believe I need to create a function (referred to as dispatch
below) that accepts a generic type of data and an identifier for the associated aggregator class. However, I am facing difficulties in properly constraining the parameters to satisfy TypeScript's requirements.
Here is what I have managed to put together so far:
enum SourceIdentifier {
A = 'a',
B = 'b'
}
interface DataA {
prop1: number,
prop2: number[],
}
interface DataB {
prop3: number,
prop4: number,
}
class BaseAggregator<Data> {
public add(data: Data) {
// Store the data to be aggregated.
}
}
class AggregatorA extends BaseAggregator<DataA> {}
class AggregatorB extends BaseAggregator<DataB> {}
const managers = {
[SourceIdentifier.A]: new AggregatorA(),
[SourceIdentifier.B]: new AggregatorB()
}
// How can I correctly constrain this function?
const dispatch = (data, source: SourceIdentifier) => {
managers[source].add(data);
};
I have attempted to utilize generics, but I keep encountering a TypeScript error:
const dispatch = <Data, Manager extends BaseAggregator<Data>>(data: Data, source: SourceIdentifier) => {
/*
* Type 'AggregatorA | AggregatorB' is not assignable to type 'Manager'.
* 'Manager' could be instantiated with an arbitrary type which could be unrelated to 'AggregatorA | AggregatorB'
*/
const manager: Manager = managers[source];
manager.add(data);
};
Is it feasible to properly constrain a function like this, or am I facing limitations due to the absence of types at runtime? I would greatly appreciate any assistance. Thank you.