Sorry if my title could be better, I have only been using typescript for about 2 weeks so my vernacular is probably lacking.
I have a structure that is 2 levels deep. For simplicity sake, let's image it such as:
type Structure = {
foo: {
a: 1,
b: 2,
}
bar: {
c: 3,
d: 4,
}
}
I have a function that takes a string like "foo.a" and returns that leaf of the structure.
The ultimate goal is to be type safe so that if I run:
const x = lookup("foo.a") // x inferred as 1
And TypeScript will know that "foo.a" is valid and the return type is 1.
I was able to create a type like this:
type Branch = keyof Structure
type Section<B extends Branch> = keyof Structure[B] & string
type Path<B extends Branch, S extends Section<B>> = `${B}.${S}`
This works but I cannot use it like so:
const path:Path = 'foo.a'
I must instead use it like:
const path:Path<"foo","a"> = 'foo.a'
This doesn't help me.
I also tried something like:
type SectionPath = `${Branch}.${Section<Branch>}`
But this becomes never
and I am assuming it is never because it would create a union that includes impossibilities like "foo.c" or "bar.a" which are invalid. Is there a way to just get the union of possibilities, in this case: "foo.a" | "foo.b" | "bar.c" | "bar.d"
I know I can define this union manually, but the real structure is much larger and would be hard to maintain them both.
Also once I have this union, and I can accept it as an argument in a function, bonus points if you can tell me how to make the function's return type, the correct type for that leaf of the structure!