I have a lot of lists that need to be casted to maps so i decided to create a listToMap
function:
export function listToMap<T>(
list: T[],
keyAccesFn: (listElement: T) => string): Map<string, T> {
const reducer = (accumulator: Map<string, T>, currentValue: T) => accumulator.set(keyAccesFn(currentValue), currentValue);
return list.reduce(reducer, new Map<string, T>());
};
the function takes a list and a function which returns a string for a list element. The result is a Map with the returned string of keyAccesFn
as key for the listelement the function was used on.
Now it occured that i not only have to extract the Maps key of the listed Objects but the value itself. I decided to apporach this by passing another function into the listToMap function which might return a new Type. The function looks like this atm:
export function listToMap2<T1, T2>(
list: T1[],
keyAccesFn: (element: T1) => string,
valueAccesFn: (element: T1) => T2 = (element: T1) => element): Map<string, T2> {
const reducer = (accumulator: Map<string, T2>, currentValue: T1) => accumulator.set(keyAccesFn(currentValue), valueAccesFn(currentValue));
return list.reduce(reducer, new Map<string, T2>());
};
The issue is: i want to provide a default valueAccessFn
that just returns the list elemnt so i could replace listToMap with listToMap2
, but can't as typescript does not accept that generic type T1
might be generic type T2
. That annoys me espacially, as i have no other place where pass anything of T2
.
There are two issues with the default you specify:
T1=T2
T1
and T2
are different types, just based on the method definition it can't tell that T1
will be compatible with T2
Both problems can be solved, the first by specifying a default value for T1
, and the second by using a type assertion to any for the default value.
export function listToMap2<T1, T2 = T1>(
list: T1[],
keyAccesFn: (element: T1) => string,
valueAccesFn: ((element: T1) => T2) = ((element: T1) => element) as any
): Map<string, T2> {
const reducer = (accumulator: Map<string, T2>, currentValue: T1) => accumulator.set(keyAccesFn(currentValue), valueAccesFn(currentValue));
return list.reduce(reducer, new Map<string, T2>());
};
listToMap2([''], k=> k) // Map<string, string>
listToMap2([''], k=> k, k=> k.length); //Map<string, number>