DEV Community

Cover image for TypeScript Utility: keyof nested object

TypeScript Utility: keyof nested object

Pedro Figueiredo on December 15, 2021

In this blog post, we will learn how to build a TypeScript util type, that exposes all the key paths of an object, including the nested ones. ...
Collapse
 
krixpello profile image
KriXPello • Edited

To hide Array methods use this:

type NestedKey<O extends Record<string, unknown>> = {
[K in Extract<keyof O, string>]: O[K] extends Array<any>
? K
: O[K] extends Record<string, unknown>
? `${K}` | `${K}.${NestedKey<O[K]>}`
: K
}[Extract<keyof O, string>];

Collapse
 
pffigueiredo profile image
Pedro Figueiredo

Yap, there are multiple ways to hide an array, if I was aiming into that, something similar to this would probably be my bet, thanks ❤️

Collapse
 
abetoots profile image
abe caymo

hi! can't thank you enough for this awesome post. still new to TS but how do I use this util for a function that returns an object which contains all keys generated from <NestedKeyOf> with values as string ?

Collapse
 
pffigueiredo profile image
Pedro Figueiredo

Hey Abe, thanks a lot for the feedback ;)

Could you try to provide me an example of what you are trying to achieve? Maybe using ts playground - you just need to edit and share the link after ;)

Collapse
 
abetoots profile image
abe caymo

so it's basically like this:

const useStyles = exposeStyles({
  merge: {
    root: "Checkbox",
    li: "Checkbox__li",
  },
  replace: {
    input: "Checkbox__input",
    description: "Checkbox__description",
  },
});

const classes = useStyles(props.classes);
Enter fullscreen mode Exit fullscreen mode

exposeStyles accepts an object where I define which keys are mergeable/replaceable. it returns a function which, when invoked, should return an object containing all those keys, like so: classes.root . I just don't know how to type that returned function

Thread Thread
 
pffigueiredo profile image
Pedro Figueiredo

I'm not 100% sure if you want to use NestedKeyOf in this scenario, and neither I'm sure of a few implementation details of your example. But take a look at this example that I started, and try to play around with it a bit, if you don't get it right, send me message over Twitter and I will help you further ;)

Collapse
 
somu93 profile image
somu93

${Key}.${NestedKeyOf<ObjectType[Key]>}. this line gives me an error when typescript version is 4.6.4 & 4.7.4 (latest) ->

Type instantiation is excessively deep and possibly infinite. Can you explain why and can you please also add the return type.

Collapse
 
kemotx90 profile image
kemotx90

use

`${Key}.${NestedKeyOf<ObjectType[Key]> extends infer U extends string ? U : never}`
Enter fullscreen mode Exit fullscreen mode

instead of

${Key}.${NestedKeyOf<ObjectType[Key]>}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
skmohammadi profile image
Karim Mohammadi

Your suggestion fixed the following TS error:

Type instantiation is excessively deep and possibly infinite.
Enter fullscreen mode Exit fullscreen mode
Collapse
 
angelocorleone profile image
Angelo Corleone

Thank you! will definitely use this helper at work :D

Collapse
 
jsonz1993 profile image
Jsonz

cool

Collapse
 
codriniftimie profile image
Codrin Iftimie

If anyone is looking for a solution that works with objects that include arrays, which would make this article complete, I stumbled upon this localcoder.org/typescript-deep-key...

In here there is a brief mention of this file used in react-hook-form.

This is the version I ended up using. This also includes methods of getting the type of the key which would come in handy

Collapse
 
pabloimrik17 profile image
Pablo F. Guerra

Hi @codriniftimie, any chance you could update your type for array with this syntax?

Instead of a.b.1 --> a.b.[1]

I would help me a lot in my current project.

Collapse
 
dzey profile image
Jakub Królak

I found this solution that I think is simpler and easier to understand

type NestedKeyOf<T, K = keyof T> = K extends keyof T & (string | number)
  ? `${K}` | (T[K] extends object ? `${K}.${NestedKeyOf<T[K]>}` : never)
  : never
Enter fullscreen mode Exit fullscreen mode
Collapse
 
akib profile image
Shuaib hasan akib • Edited

Genius!