1

How to make a recursive tree-like tuple?

I have a function for recursively getting the value of an object's property:

function getValue(obj: object, ...keys: string[]): any

and here is what it does given an object:

const testObject = {
  hello: {
    world: "Hello world!",
    user: "Hello user!"
  },
  first: {
    second: 2
  },
  shallow: {
    deep: true
  }
}
console.log(getValue(testObject, "first")); // { second: 2 }
console.log(getValue(testObject, "hello", "world")); // Hello world!
console.log(getValue(testObject, "shallow", "deep")); // true

My goal is adding autocomplete into the function parameters:

function getValueTyped<T extends object>(obj: T, ...keys: TreeKeys<T>): any

Please note that this function should be able to work with any given object type!

and the concept is (with the same object as above):

getValueTyped<typeof testObject>(
  testObject,
  "hello", // This parameter shows as a union: ("hello" | "first" | "shallow")
  "world" // IF the previous parameter is "hello", than this one is ("world" | "user")
);
getValueTyped<typeof testObject>(
  testObject,
  "first", // This parameter shows as a union: ("hello" | "first" | "shallow")
  "second" // IF the previous parameter is "first", than this one is only "second"
);

While trying to solve this, I came up with a few things. The type of the keys argument should be a tuple with generics, something like this:

type TreeKeys<T extends object, K extends keyof T = keyof T> = [
  K, // The first property
  ...(K extends object ? TreeKeys<T[K], keyof T[K]> : [])
];

but it obviously didn't work. I think using infer might help, but I am not sure in how to implement this or if this is even possible. If this is still not possible but there is a proposal, I would like to take a look at it.

Any help would be appreciated!

  • This sort of thing is tricky; see the answer to the linked question for more information. [This playground link](https://tsplay.dev/wjXl6m) is how I might approach it for the example in this question. IntelliSense/auto-complete is a bit funky but this is the closest I can get and still have it behave the way you are suggesting. If this doesn't meet your needs you might want to open a new question where you explicitly reference the linked question above and how the solution there doesn't work for you. Good luck! – jcalz Dec 26 '22 at 14:44

0 Answers0