Skip to content

Instantly share code, notes, and snippets.

@bdsqqq
Created February 9, 2022 22:48
Show Gist options
  • Save bdsqqq/efe4dfbdbec380cc3387761ea9b90aee to your computer and use it in GitHub Desktop.
Save bdsqqq/efe4dfbdbec380cc3387761ea9b90aee to your computer and use it in GitHub Desktop.
A way to get deeply nested types like if you were using `keyof`, it supports full blown path threes and just leaves too.

I really wanted to get a type-safe function from an i18n lib I was using so I found this in a forum I never heard of. Enjoy!

// From https://ostack.cn/qa/?qa=416461/
type Cons<H, T> = T extends readonly any[]
  ? ((h: H, ...t: T) => void) extends (...r: infer R) => void
    ? R
    : never
  : never;

type Prev = [
  never,
  0,
  1,
  2,
  3,
  4,
  5,
  6,
  7,
  8,
  9,
  10,
  11,
  12,
  13,
  14,
  15,
  16,
  17,
  18,
  19,
  20,
  ...0[]
];

// type NestedObjectPaths = "a" | "b" | "nest" | "otherNest" | "nest.c" | "otherNest.c"
type Paths<T, D extends number = 10> = [D] extends [never]
  ? never
  : T extends object
  ? {
      [K in keyof T]-?: K extends string | number
        ? `${K}` | Join<K, Paths<T[K], Prev[D]>>
        : never;
    }[keyof T]
  : "";

type Join<K, P> = K extends string | number
  ? P extends string | number
    ? `${K}${"" extends P ? "" : "."}${P}`
    : never
  : never;
// type NestedObjectLeaves = "a" | "b" | "nest.c" | "otherNest.c"
type Leaves<T, D extends number = 10> = [D] extends [never]
  ? never
  : T extends object
  ? { [K in keyof T]-?: Join<K, Leaves<T[K], Prev[D]>> }[keyof T]
  : "";
@bdsqqq
Copy link
Author

bdsqqq commented Feb 9, 2022

btw, shout out to 深蓝, I can't read your name but you made my life way easier with this answer!

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