Skip to content

Instantly share code, notes, and snippets.

@VladSez
Last active February 13, 2023 14:08
Show Gist options
  • Save VladSez/fd3cdc2384a889903ebceade44a15a17 to your computer and use it in GitHub Desktop.
Save VladSez/fd3cdc2384a889903ebceade44a15a17 to your computer and use it in GitHub Desktop.
AllPaths
// 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