Need help creating an array from an object to render data

I’m converting an object into an array but typescript throws and error:

“Property ‘map’ does not exist on type ‘unknown'”

(Yes, I googled that error but nothing very clear on the web)

LIVE DEMO

In this live demo you will not see the typescript error but in my Angular app I can see it and it’s causing issues :(.

Does anyone know how to convert this object to the same array shown on my live demo using lodash or Javascript? Thanks a lot in advance!

This is the code:

dataObject = {
A: [
    {id: 1, name: 'Mike', lastname: 'asmith'},
    {id: 2, name: 'Mary', lastname: 'alters'},
    {id: 3, name: 'Boris', lastname: 'al'}
],
B: [
    {id: 1, name: 'Lauren', lastname: 'bmith'},
    {id: 2, name: 'Travis', lastname: 'balters'},
    {id: 3, name: 'Barn', lastname: 'bl'}
], 
...
}
  
dataObjectDisp = Object.entries(this.dataObject).reduce((prev, [key, value]) =>{
  return [...prev, ...value.map((user, index) => ({ 
    ...user, parent: key, index }))]
}, []);

This is the output that I want:

 [
  {
    "id": 1,
    "name": "Mike",
    "lastname": "asmith",
    "parent": "A",
    "index": 0
  },
  {
    "id": 2,
    "name": "Mary",
    "lastname": "alters",
    "parent": "A",
    "index": 1
  },
  ...
]

Answer

TS can’t infer the type of Array.reduce() accumulator (the empty array at the end). You can set the accumulator as the type of array you wish to get in the end (TS Playground):

type Obj = {
  "id": number,
  "name": string,
  "lastname": string,
  "parent": string,
  "index": number
};

export class AppComponent implements OnInit {
...
    dataObjectDisp = Object.entries(this.dataObject).reduce((prev, [key, value]) =>{
      return [...prev, ...value.map((user, index) => ({ 
        ...user, parent: key, index }))]
    }, [] as Obj[])   
...
}

Another option is to use Array.flatMap() instead of array reduce, but you’ll need to change the target in TS Config to es2019 (TS Playground):

export class AppComponent implements OnInit {
...
    dataObjectDisp = Object.entries(this.dataObject).flatMap(([key, value]) =>
      value.map((user, index) => ({ ...user, parent: key, index }))
    )
...
}

And if you use lodash, you can use _.flatMap() without changing the target (TS Playground):

import { flatMap } from 'lodash';

export class AppComponent implements OnInit {
...
    dataObjectDisp = flatMap(Object.entries(this.dataObject), ([key, value]) =>
      value.map((user, index) => ({ ...user, parent: key, index }))
    )
...
}

Leave a Reply

Your email address will not be published. Required fields are marked *