Usually when we are fetching we get an array with complex objects with ids. Like this:
const arrayOfObjects = [
{
id: '56gfl3Y23',
brand: 'Bosch',
price: 1234,
specs: ['feature1', 'feature2', 'reature3'],
// ... other fields
},
// ... other objects
]
In Javascript we may simply use reduce method to create an array of objects with id as a key.
const productsById = arrayOfObjects.reduce((acc, product) => {
acc[product.id] = product;
return acc;
}, []);
There`s no problem to describe interface of a product like
interface IProduct {
id: string,
brand: string,
price: number,
specs: string[],
// ...
}
But when I try to describe this reduce function I absolutely get stucked. I suppose I need to use a generic, but this did not help as it throws an error Element implicitly has an 'any' type because index expression is not of type 'number'.
How can I resolve it without using any
?
CodePudding user response:
[]
creates an array - if your indicies aren't in ascending numeric order, use a plan object instead, with {}
. One option is to use generics to indicate that that accumulator object is of type Record<string, IProduct>
.
const productsById = arrayOfObjects.reduce<Record<string, IProduct>>((acc, product) => {
acc[product.id] = product;
return acc;
}, {});
A quicker way is to use Object.fromEntries
.
const productsById = Object.fromEntries(
arrayOfObjects.map(obj => [obj.id, obj])
);
CodePudding user response:
From what you're trying to assign, you should start with an object. The type can either be a Record or a typed object.
const productsById = arrayOfObjects.reduce((acc, product) => {
acc[product.id] = product;
return acc;
}, {} as Record<string,IProduct>); // or {[id: string]: IProduct}
as an extra, you can use lodash to key by a property.
const productsById = _.keyBy(arrayOfObjects, 'id')