Skip to content

Instantly share code, notes, and snippets.

@Phryxia
Last active June 28, 2024 06:06
Show Gist options
  • Save Phryxia/4f043ea22b671d6b1e27416651969099 to your computer and use it in GitHub Desktop.
Save Phryxia/4f043ea22b671d6b1e27416651969099 to your computer and use it in GitHub Desktop.
TypeScript snippets for nested object types
export type DeepKeys<T, K = keyof T, R extends string[] = []> =
K extends keyof T ?
T[K] extends object ?
T[K] extends unknown[] | [unknown, ...unknown[]] ?
[...R, K] | [...R, K, KeyOfArrayLike<T[K]>]
: [...R, K] | [...R, K, ...DeepKeys<T[K], keyof T[K], R>]
: [...R, K]
: []
type KeyOfArrayLike<T> =
T extends [] ?
never
: T extends [unknown, ...infer R] ?
R['length'] | KeyOfArrayLike<R>
: T extends unknown[] ?
number
: never
export type DeepValue<T, P extends (string | number)[]> =
P extends [infer K, ...infer Rest extends (string | number)[]] ?
K extends keyof T ?
Rest extends [] ?
T[K]
: DeepValue<T[K], Rest>
: never
: never
@Phryxia
Copy link
Author

Phryxia commented Jun 28, 2024

DeepKeys<T> resolve every possible key path to the leaf properties in nested object.

type U = DeepKeys<{
    y: {
        z: 'a'
        h: [number, number]
        arr: string[]
    }
    a: number
}>
/*
  ["a"] | ["y"] | ["y", "z"] | ["y", "h"] | ["y", "h", 0 | 1] | ["y", "arr"] | ["y", "arr", number]
*/

DeepValues<T, P> resolve the type of value of nested properties of T with path of P.

interface X {
    y: {
        z: 'a'
        h: [number, 'b']
        arr: string[]
    }
    a: number
}

DeepValue<X, ['y', 'h', 0]> // number
DeepValue<X, ['y', 'arr', 0]> // string
DeepValue<X, ['y', 'z']> // a

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