'Typescript typesafe generic function to collect array to map based on specified property key
I am trying to write a typescript generic function which, passed an array T[] and a property key TProp where TProp extends keyof T and such that T[TProp] extends PropertyKey, will collect the elements of the array into a single object, with the value selected from the array element based on the specified property as the key mapping to the original object in the array (keeping latest if there are duplicates).
I have the following code so far
type KeysWithValueOfType<T, V> = keyof {
[P in keyof T as T[P] extends V ? P : never]: P;
} &
keyof T;
export const CollectToMap = <
TArray extends object,
TProp extends KeysWithValsOfType<TArray, PropertyKey>,
TKey extends PropertyKey = TArray[TProp]
>(
arr: TArray[],
property: TProp
): Partial<Record<TKey, TArray>> => {
let result: Partial<Record<TKey, TArray>> = {};
for (const element of arr) {
result[element[property]] = element;
}
return result;
};
KeysWithValueOfType returns a union type of keys from T for which T[Property] extends V.
For example given the type Person
type Person = {
name?: string;
age: number;
email: string;
pets: string[];
};
type PersonStringPropKeys = KeysWithValueOfType<Person, string>; is equivalent to type PersonStringPropKeys = 'email'; which looks right.
Using this in CollectToMap however, I am seeing compiler errors for the TKey type, highlighting TArray[TProp] with the error
Type 'TArray[TProp]' does not satisfy the constraint 'PropertyKey'. Type 'TArray[KeysWithValsOfType<TArray, PropertyKey>]' is not assignable to type 'PropertyKey'.
Type 'TArray[string] | TArray[number] | TArray[symbol]' is not assignable to type 'PropertyKey'. Type 'TArray[string]' is not assignable to type 'PropertyKey'.ts(2344)
Subsequently there is also a compiler error on the line result[element[property]] = element; with the error
Type 'TArray[TProp]' cannot be used to index type 'Partial<Record<TKey, TArray>>'.ts(2536)
It seems that I have wrongly expressed the semantics I'm trying to convey, or that the compiler is unable to follow that if TProp is a keyof T where T[TProp] extends PropertyKey it can therefore be used in the way I'm intending to index into the Record.
What's strange is that writing a simple test example using the function, the compiler does seem to give correct suggestions for the keys which are valid, and infer the correct types.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|


