Last active
February 13, 2023 14:08
-
-
Save VladSez/fd3cdc2384a889903ebceade44a15a17 to your computer and use it in GitHub Desktop.
AllPaths
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://mobile.twitter.com/AndaristRake/status/1625130160277028864 | |
// https://twitter.com/GabrielVergnaud/status/1623814585445675008?s=20&t=iG8sUzPLNZNgog-tAttHiw | |
type AllPaths<T> = | |
// if `T` is an object with string keys | |
T extends Record<string, unknown> | |
// Assign the union `keyof T` to a variable `K` | |
? keyof T extends infer K | |
// We distribute K. | |
// For each member in `K`: | |
? K extends string | |
// Concat `K` with the rest of the path | |
? K | `${K}.${AllPaths<T[K]>}` | |
// unreachable branch (`K` is always a string) | |
: never | |
// unreachable branch (`extends infer` is always truthy) | |
: never | |
// if `T` isn't a record, we return the empty type | |
: never; | |
type Result = AllPaths<{ | |
idle: unknown; | |
loading: unknown; | |
other: { | |
awesome: { | |
foo: unknown; | |
}; | |
}; | |
yet: { | |
another: {}; | |
}; | |
}>; | |
type Display = Result; | |
// ^? | |
// alternative | |
const hugeObj = { a0: { a1: { a2: { a3: { a4: { a5: { a6: { a7: { a8: { a9: { a10: { a11: { a12: { a13: { a14: { a15: { a16: { a17: { a18: { a19: { a20: { a21: { a22: { a23: { a24: { a25: { a26: { a27: { a28: { a29: { a30: { a31: { a32: { a33: { a34: { a35: { a36: { a37: { a38: { a39: { a40: { a41: { a42: { a43: { a44: { a45: { a46: { a47: { a48: { a49: { a50: { a51: { a52: { a53: { a54: { a55: { a56: { a57: { a58: { a59: { a60: { key: 'a' } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } | |
type JoinPath< | |
A extends string, | |
B extends string | |
> = [A] extends [never] ? B : [B] extends [never] ? A : `${A}.${B}`; | |
type AllPaths<T, Path extends string = never, R extends string = never> = | |
T extends Record<string, unknown> | |
? keyof T extends infer K | |
? K extends string | |
? AllPaths<T[K], JoinPath<Path, K>, R | JoinPath<Path, K>> | |
: never | |
: never | |
: R; | |
type Result2 = AllPaths<typeof hugeObj>; | |
type Display2 = Result2; | |
// ^? |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment