I have a Datum<T> type where T may be either a number or a string. Datums are collected as arrays in an object. I have an aggregateDatums function that takes object, key name with Datums array, and returns a datum as well.
export interface Datum<T extends string | number> {
key: T;
count: number;
}
const aggregateDatums = <
TKey extends string | number,
T extends { [k in K]: Datum<TKey>[] },
K extends keyof T
>(data: T, key: K): Datum<TKey>[] => {
return [];
};
const data = {
numeric: [{key: 1, count: 1}, {key: 2, count: 2}],
text: [{key: 'a', count: 1}, {key: 'b', count: 2}],
};
const aggregated = {
numeric: aggregateDatums(data, 'numeric'), // should be type Datum<number>[], but is Datum<string | number>[]
text: aggregateDatums(data, 'text'), // should be type Datum<string>[], but is Datum<string | number>[]
};
Because I pass an object and a key that holds array, not an array of Datums directly, the result is typed Datum<string | number>[]. My goal is the type to correspond to the type of Datums in source array, so Datum<string>[] or Datum<number>[]. Any tips on how can I achieve this?
The example is simplified to show the problem only. But if I overengineered typings that can be done simpler, please let me know.
Also, I would be grateful if someone can recommend resources on advanced typings in TypeScript. Unfortunately, most resources is about types like Partial<T> etc, while I know you can do advanced magic with types :-)