Utilizing the reducer pattern can effectively handle both type and runtime scopes.
export interface SomeNumbers<N, V> {
name: N;
value: V;
}
type Reducer<
Tuple extends Array<any>,
Acc extends Record<string, any> = {},
Index extends number[] = []
> =
Tuple extends []
? Acc
: (Tuple extends [infer Head, ...infer Tail]
? (Head extends PropertyKey
? Reducer<
Tail,
Acc & Record<Head, SomeNumbers<Head, Index['length']>>,
[...Index, 1]
>
: never)
: never)
const generator = <Tuple extends string[]>(tuple: [...Tuple]) =>
tuple.reduce((acc, elem, index) => ({
...acc,
[elem]: {
name: elem,
value: index
}
}), {} as Reducer<Tuple>)
const output = generator(['first', 'second', 'third'])
// {
// name: "first";
// value: 0;
}
output.first
Interactive Demo
Reducer
type performs a similar function to the generator
function. However, Reducer
recursively iterates through the tuple.
Reducer
- recursively traverses the Tuple
and merges Acc
with SomeNumbers<N,V>
. Index
- serves as an additional tuple for indexing. The value in Index
increases by 1 element each iteration, corresponding to the index of the currently processed element
For more examples, check out my blog