To enhance the functionality of arrayToObject()
, you can make it generic by allowing both the array element type T
and the key type K
to be specified, and then constrain T
so that its property at key K
must be of type string
:
const arrayToObject = <T extends Record<K, string>, K extends keyof T>(
array: T[], key: K
): Record<string, T> => {
return array.reduce<Record<string, T>>(
(accumulator, currentValue) =>
Object.assign(accumulator, {
[currentValue[key]]: currentValue,
}),
{}
);
};
This will compile without any errors. Testing it out:
interface Bar {
a: number,
b: string,
c: boolean
}
const bars: Bar[] = [
{ a: 1, b: "alpha", c: true },
{ a: 2, b: "beta", c: false },
{ a: 3, b: "gamma", c: true }
];
const result = arrayToObject(bars, "b"); // This is valid
Object.entries(result).forEach(
([k, v]) => console.log(k, v.a.toFixed(1), v.b.toUpperCase())
);
/* "alpha", "1.0", "ALPHA"
"beta", "2.0", "BETA"
"gamma", "3.0", "GAMMA" */
arrayToObject(bars, "a") // This will produce an error
// ----------> ~~~~
// The types of property 'a' are incompatible.
The code seems to be working fine. The compiler will accept correct calls and flag any incorrect key assignments, providing clear error messages if needed.
Link to code on the TypeScript Playground