For some unknown reason, I am attempting to implement a reduce method on a subclass of Map:
const nah = Symbol('not-an-arg');
class MapArray<A, B> extends Map<A, B> {
reduce<T = [A, B]>(f: (prev: T, next: [A, B]) => any, initialVal?: T) {
let prev = arguments.length > 1 ? arguments[1] : nah;
for (const [k, v] of this) {
if (prev === nah) {
prev = [k, v];
continue;
}
prev = f(prev, [k, v]);
}
return prev;
}
}
While it may not be the most elegant solution, it does work. However, the issue lies with the typing. Consider the following scenarios:
new MapArray<string,boolean>().reduce((a,b) => 'whatever');
Versus:
new MapArray<string,boolean>().reduce((a,b) => 'whatever', []);
I want the method to capture the type of the second argument []
.
In my attempt with TypeScript, I tried something like this using an invalid version:
type X = (if initialVal ? typeof initialVal : [A, B])
reduce<R = any, T = X>(f: (prev: T, next: [A, B]) => R, initialVal?: T);
Clearly, this is incorrect but the intention was to capture the type of initialVal
if it's provided, otherwise default to [A,B]
. Is there a way to achieve this?
See the problem in action at: TS playground
During execution, the error "a is not iterable" occurs when a is assigned a value of 55.