0

I'm learning TypeScript and I have a situation where I am mapping an array of objects where each object can have different fields -- or to be specific, a field in the object is an object that can have different fields.

I'm not sure how to write an interface for this.

For instance, let's say I am trying to map my original data, which is Array<any> to an array whose array elements will look like this:

 [  {
      name:string,
     favorites: {
                 "spaghetti": number,
                 "fusilli": number,
                "linguine": number
                  } ,
    } ,

{
       name:string,
      favorites: {
                 "spaghetti": number,
                 "fusilli": number,
                "farfalle": number
                  } ,


    } ]

The issue here is that the 'favorites' object can contain a wide variety of fields (all of them numbers) that have different possible names that I don't know ahead of time.

I thought of something like this

interface PastaData {
   [key: string] : number,
}

interface UserData {
    name: string,
    favorites: Array<PastaData>
}

const ParsedUserData: Array<UserData> = originalData.map(data  => ({name:data.name,favorites:data.favorites}));

with the original data being of this format (this is truncated, of course):

[
  {
    "_id": "5bb238cbf839d08d65633450",
    "index": 0,
    "guid": "390322bb-3e93-4196-853a-e6e7a6f455bb",
    "isActive": true,
    "balance": "$2,193.03",
    "picture": "http://placehold.it/32x32",
    "age": 62,
    "eyeColor": "brown",
    "name": "Holder Joyce",
    "gender": "male",
    "company": "RAMEON",
    "email": "[email protected]",
    "phone": "+1 (942) 548-3425",
    "address": "168 Ovington Court, Eagleville, Oregon, 1098",
    "about": "Voluptate eiusmod exercitation ad aliqua ullamco ex officia. Fugiat deserunt anim commodo anim reprehenderit cillum cupidatat magna anim. Do in sint elit deserunt sint amet veniam culpa et veniam.\r\n",
    "registered": "2017-09-21T02:55:55 -02:00",
    "latitude": 53.144539,
    "longitude": 111.973422,
    "favorites": {
      "cavatappi": 3.1604049168546533,
      "fusilli": 47.41214262743145,
      "spaghetti": 36.351431171952584,
      "tagliatelle ": 16.540786406823592,
      "farfalle": 29.91825944401951
    }
  },
  {
    "_id": "5bb238cba65b6203c1060042",
    "index": 1,
    "guid": "8f258a51-4b30-45ab-8bd3-100afb9aa191",
    "isActive": true,
    "balance": "$3,852.51",
    "picture": "http://placehold.it/32x32",
    "age": 29,
    "eyeColor": "blue",
    "name": "Calhoun Mclean",
    "gender": "male",
    "company": "GOGOL",
    "email": "[email protected]",
    "phone": "+1 (840) 550-3492",
    "address": "775 Arion Place, Barstow, South Dakota, 3519",
    "about": "Id cillum nulla laborum anim enim magna ea. Amet irure exercitation culpa deserunt culpa duis enim ullamco do do. Aliqua commodo occaecat cillum culpa est aliquip veniam officia quis cillum nisi.\r\n",
    "registered": "2015-12-11T06:06:10 -01:00",
    "latitude": -85.141798,
    "longitude": 100.30676,
    "favorites": {
      "cavatappi": 36.419432034499955,
      "fusilli": 84.64117075525127,
      "spaghetti": 86.77410379301949,
      "tagliatelle ": 77.02196537202377,
      "farfalle": 70.6367456562684
    }
  },]

But that doesn't work. I get the following error

enter image description here

How do I make an interface for an object whose field names can have a number of different values, that I don't know, but whose types are all number?

Thanks for any help!

2
  • For this to constitute a minimal reproducible example you should provide an example originalData variable that shows the problem without being a million lines long. Right now all we can do is guess based on your description. I'd say... PastaData should be {[k: string]: number | undefined}, since when you access a property at a particular key you'll have to check if it's defined or not. Again, though, that's just a guess, since we can't reproduce your issue as stated. Commented Jun 8, 2019 at 19:30
  • @jcalz, I added the data. That was indeed my original thought, to add | undefined, but it makes no difference. Commented Jun 8, 2019 at 19:37

2 Answers 2

4

Your issue is that according to your data sample, favorites property is not an array but an object with [key: string]: number typed properties!

"favorites": {
  "cavatappi": 3.1604049168546533,
  "fusilli": 47.41214262743145,
  "spaghetti": 36.351431171952584,
  "tagliatelle ": 16.540786406823592,
  "farfalle": 29.91825944401951
}

Therefore you should change the type of UserData.favorites property to PastaData instead of Array<PastaData>.

interface PastaData {
  [key: string] : number,
}

interface UserData {
    name: string,
    favorites: PastaData // instead of Array<PastaData>
}

const ParsedUserData: Array<UserData> = originalData.map(data  => ({name:data.name,favorites:data.favorites}));

TypeScript example available here (don't mind the Angular code):
https://stackblitz.com/edit/angular-stackoverflow-56509473

Sign up to request clarification or add additional context in comments.

Comments

1

Your problem is that you say that .favorites is an array of PastaData, but you provide a single PastaData instead.

Change:

.map(data  => ({ name: data.name, favorites: data.favorites }))

to:

.map(data  => ({ name: data.name, favorites: [ data.favorites ] }))

And then you'll be producing UserData-shaped values.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.