3

I am completely new to Typescript and have been able to make some progress in other areas but am struggling with creating interfaces for the deeply nested objects with "taskName" and "totalTaskHours". The data looks like this:

[
    {
      "20229622": [
        {
          "taskName": "Project Management",
          "totalTaskHours": "1589.4"
        },
        {
          "taskName": "Marketing",
          "totalTaskHours": "1306.8"
        },
        {
          "taskName": "Design",
          "totalTaskHours": "212.4"
        },
        {
          "taskName": "Programming",
          "totalTaskHours": "415.8"
        }
      ]
    },
    {
      "20229623": [
        {
          "taskName": "Project Management",
          "totalTaskHours": "980.1"
        },
        {
          "taskName": "Marketing",
          "totalTaskHours": "717.3"
        },
        {
          "taskName": "Design",
          "totalTaskHours": "468.9"
        }
      ]
    },
    {
      "20229624": [
        {
          "taskName": "Programming",
          "totalTaskHours": "5930.1"
        },
        {
          "taskName": "Project Management",
          "totalTaskHours": "997.2"
        },
        {
          "taskName": "Marketing",
          "totalTaskHours": "2108.69"
        },
        {
          "taskName": "Design",
          "totalTaskHours": "529.2"
        }
      ]
    }
  ]

I have tried to get down to the objects inside the nested array but I am getting errors each time.

missing_other_nested_objects

I have tried with the following (obviously wrong):

interface TaskItem {
  taskName: string;
  totalTaskHours: string;
}

interface TaskItemArray {
  [key:string]: {
    [key:string]: TaskItem[];
  };
}
interface TaskBreakdownSummedByCategory {
  [key:string]: TaskItemArray[];
}

I have also tried the following but the data is too shallow:

interface TaskItem {
  taskName: string;
  totalTaskHours: string;
}
interface TaskBreakdownSummedByCategory {
  [key:string]: TaskItem;
}

Can someone help me out really quick with this issue? I am still learning but the basic tutorials dont really go through deep nested objects. Thanks!

2
  • That's a really unfortunate data structure (those objects with a single property name that varies). Do you have the option to change it? Commented Mar 18, 2019 at 14:07
  • Unfortunately, I dont have the option to change. It's the response JSON object from API call. Commented Mar 18, 2019 at 14:16

1 Answer 1

1

You're really close. Since your outer array is an array, you can just define the type of its elements (TaskItemHolder below):

interface TaskItem {
  taskName: string;
  totalTaskHours: string;
}

interface TaskItemHolder {
  [key: string]: TaskItem[];
}

Then the type for your overall array is TaskItemHolder[].

Live on the playground

That said, the above would allow multiple properties on TaskItemHolder rather than just the one. As I mentioned in a comment, if you can change the structure, I would. Having an object with one property whose name varies isn't a good idea (not even when not using static typing, but particularly when you are).


If you were to loop through that data, because of the problematic structure, you'd probably use Object.keys(...)[0] to get the key of the one property (or Object.entries(...)[0] to get the key and the value, or just Object.values(...)[0] to get the value):

for (const holder of data) {
  const key = Object.keys(holder)[0];
  console.log("Holder with key " + key + ":");
  for (const entry of holder[key]) {
    console.log(entry.taskName);
  }
}

Live copy

or just use that array of keys/entries/values if there can be other properties in a holder:

for (const holder of data) {
  for (const [key, value] of Object.entries(holder)) {
    console.log("Holder with key " + key + ":");
    for (const entry of value) {
      console.log(entry.taskName);
    }
  }
}

Live copy

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

5 Comments

Thanks for the quick reply. I have also tried that approach but the 2nd and 3rd items have the key with "undefined" instead of {taskName: string; totalTaskHours: string;}.
@technicacreativejp - I don't follow you, what do you mean by "the 2nd and 3rd items"? There is exactly one item array per holder in the data, and the entries in that array aren't undefined.
Im getting this when I added the []: Type '({ "20229622": { taskName: string; totalTaskHours: string; }[]; "20229623"?: undefined; "20229624"?: undefined; } | { "20229623": { taskName: string; totalTaskHours: string; }[]; "20229622"?: undefined; "20229624"?: undefined; } | { ...; })[]' is not assignable to type 'TaskBreakdownSummedByCategory[]'. Property '"20229623"' is incompatible with index signature. Type 'undefined' is not assignable to type 'TaskItem[]'.
@technicacreativejp - You don't need TaskBreakdownSummedByCategory (that is, for the data structure you've shown), just what's shown in the answer. If you need TaskBreakdownSummedByCategory for something else, please say what you need it for and how it's used.
how to combine both the interfaces?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.