Typescript: Convert an array of objects to object with ID as a key and correct typing

Kasama Chenkaow
2 min readAug 31, 2023

--

If you have an array of objects like this

type A = {
id: '001' | '002'
value: unknown
}
const arr = [
{ id: '001', value: 'anything' },
{ id: '002', value: 'anything' },
]

And want to transform the arr to this

const obj = {
'001': { id: '001', value: 'anything' },
'002': { id: '002', value: 'anything' },
}

The implementation shouldn’t be much of the problem because you can simply create a function that accepts (arr: T[], idKey: keyof T) and use reduce() or just do Object.fromEntries(arr.map(a => [a[idKey], a])) then it should work at runtime

But how do we deal with the type of that function to make sure these 2 things in checked

  1. The idKey parameter should not be any key but only the keys that satisfy object’s key constraint (`string | number | symbol`)
  2. The return type object’s keys need to be the value of that idKey parameter

This is one of the possible solutions

type AnyObject<TValue> = { [key: string]: TValue }
type StringKeys<T> = {
[K in keyof T]: T[K] extends string | number | symbol ? K : never;
}[keyof T];
const arrayToKeyObject =
<T extends Record<StringKeys<T>, string | number | symbol>, TKeyName extends keyof Record<StringKeys<T>, string | number | symbol>>(array: T[], key: TKeyName): Record<T[TKeyName], T> =>
Object.fromEntries(array.map(a => [a[key], a])) as Record<T[TKeyName], T>

playground

--

--