Accessing nested arrays with dynamic depth via indices

I’m fairly new to typescript and I have some issues to access an object in array with dynamic depth. For example:

export interface folder{
 name: string,
 type: string,
 position: number[], // index for each depth level
 children: folder[]
{
  "name": "Folder1",
  "depth": 0,
  "position": [0] // indeces for each depth level
  "children": [
    {
      "name": "Folder2",
      "depth": 1,
      "position": [0,0] // indeces for each depth level
      "children": [
        {
          "name": "Folder3"
          "depth": 2,
          "position": [0,0,0] // indeces for each depth level
        },
        {
          "name": "Folder4"
          "depth": 2,
          "position": [0,0,1] // indeces for each depth level
        }
      ]
    }
  ]
}

To get Folder4 I’d use the dot notation like: this.folder[0].children[0].children[1]

Now I was wondering, if there is a way to dynamicly access the object via the position array without iterating over the whole structure. I managed to get it working by defining a string and adding ".children[PositionIndex]" for each value in position and executing it with eval. However that is obviously not a reasonable/safe way to do this.

Any help would be greatly apprecieated.Thanks!

Answer

Instead of having a “position” field that describes the path to a certain depth/folder nested deeply into the structure itself, have a second, shallow structure that maps folder names to depths and use it to reach a folder:

const folders = {
  "name": "Folder1",
  "depth": 0,
  "position": [0], // note: this is wrong, folder one isn't nested and therefor has a position of []
  "children": [
    {
      "name": "Folder2",
      "depth": 1,
      "position": [0,0],
      "children": [
        {
          "name": "Folder3",
          "depth": 2,
          "position": [0,0,0]
        },
        {
          "name": "Folder4",
          "depth": 2,
          "position": [0,0,1]
        }
      ]
    }
  ]
};

const folderDepths = {
  // this maps depths to folders. note that "folder1" does not have a
  // depth, because it is the root node and is not nested. this means
  // that all nodes nested below folder1 have one path segment less
  // compared to your original structure.
  Folder1: [],
  Folder2: [0],
  Folder3: [0, 0],
  Folder4: [0, 1]
};

const accessFolder = (name, depths, tree) => {
  // we use this function to access (sub-)folders. it takes the name
  // of the folder to reach, the depths-mapping and the original
  // structure. stops when there are no more children to dig into or
  // the final depth is reached. returns the accessed (sub-)tree.
  let retv = tree;
  let path = depths[name];
  for (let i = 0; i < path.length && retv; i += 1) {
    if (retv.children && retv.children[path[i]]) {
      retv = retv.children[path[i]];
    }
  }
  return retv;
}



console.log(accessFolder('Folder2', folderDepths, folders));
console.log(accessFolder('Folder4', folderDepths, folders));