Reputation: 2477
I have a Datum<T>
type where T
may be either a number
or a string
. Datum
s are collected as arrays in an object. I have an aggregateDatums
function that takes object, key name with Datum
s 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 Datum
s directly, the result is typed Datum<string | number>[]
. My goal is the type to correspond to the type of Datum
s 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 :-)
Upvotes: 0
Views: 82
Reputation: 3594
const aggregateDatums = <
T extends { [k in K]: Datum<string | number>[] },
K extends keyof T
>(data: T, key: K): T[K] extends Datum<infer P>[] ? Datum<P>[] : never => {
throw 'implemented';
};
Upvotes: 1