Skip to content

Instantly share code, notes, and snippets.

@pffigueiredo
Created December 17, 2021 15:38
Show Gist options
  • Save pffigueiredo/9161240b8c09d51ea448fd43de4d8bbc to your computer and use it in GitHub Desktop.
Save pffigueiredo/9161240b8c09d51ea448fd43de4d8bbc to your computer and use it in GitHub Desktop.
NestedKeyOf
type NestedKeyOf<ObjectType extends object> =
{[Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends object
? `${Key}` | `${Key}.${NestedKeyOf<ObjectType[Key]>}`
: `${Key}`
}[keyof ObjectType & (string | number)];
@jomifepe
Copy link

jomifepe commented Dec 21, 2021

Extremely useful type 🚀

Here's a quick way to prevent it from iterating through array structures:

type NestedKeyOf<ObjectType extends object> = 
{[Key in keyof ObjectType & (string | number)]: ObjectType[Key] extends object ? 
    ObjectType[Key] extends { pop: any; push: any } ? `${Key}` : `${Key}` | `${Key}.${NestedKeyOf<ObjectType[Key]>}`
: `${Key}`
}[keyof ObjectType & (string | number)];

@JWThewes
Copy link

Any idea on how to support optional types here?
Let's imagine I do have to following object:
{
name: string,
address?: {
city: string
}
}

In this case this solution doesn't work. Any solution for this?

@pffigueiredo
Copy link
Author

@JWThewes one could extract the "object" from the T | undefined union with the following intersection T & {}, which matches any non-null object.

So, something like this should do the trick, not sure if it has extra side-effects, but it shouldn't.

type NestedKeyOf<ObjectType extends object> = 
{[Key in keyof ObjectType & (string | number)]: ObjectType[Key] & {} extends object
? `${Key}` | `${Key}.${NestedKeyOf<ObjectType[Key] & {}>}`
: `${Key}`
}[keyof ObjectType & (string | number)];

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment