I'm looking for nested object paths: Is something like this possible?
interface IHuman {
age: number;
friend: {
name: string;
}
}
keyof IHuman; // "age", "friend.name"
type AnyObject = Record<string, any>
type DotJoin<A extends string, B extends string> = A extends '' ? B : `${A}.${B}`
type DeepKeys<O extends AnyObject> = {
[K in keyof O]: O[K] extends AnyObject ? K : never
}[keyof O]
// @ts-expect-error Type 'keyof O' does not satisfy the constraint 'string'.
type DotBranch<O extends AnyObject, P extends string = '', K extends string = keyof O> =
K extends DeepKeys<O>
? DotBranch<O[K], DotJoin<P, K>>
: /*************/ DotJoin<P, K>
interface Obj {
a: {
x: string
y: {
z: string
}
}
b: {
u: boolean
}
c: number
}
type D = DotBranch<Obj> // type D = "c" | "a.x" | "a.y.z" | "b.u"
declare function get(path: DotBranch<Obj>)
get('') // Argument of type '""' is not assignable to parameter of type '"c" | "a.x" | "a.y.z" | "b.u"'.
Typescript Playground
GitHub Gist
I don't think this is possible, as for why i can make a wild guess:
interface IHuman {
age: number;
'friend.name': any;
friend: {
name: string;
}
}
const b: keyof IHuman = 'friend.name';
friend.name
would now be ambigious.
I've not found a nice solution for this too. But you might want to take a look at typed-path project.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With