Home > OS >  Type reduce array return objects bu id
Type reduce array return objects bu id

Time:07-16

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')
  • Related