export type GenericObject = Record; type Join = L extends string | number ? R extends string | number ? `${L}.${R}` : L : R extends string | number ? R : undefined; type Union = L extends undefined ? R extends undefined ? undefined : R : R extends undefined ? L : L | R; /** * NestedPaths * Get all the possible paths of an object * @example * type Keys = NestedPaths<{ a: { b: { c: string } }> * // 'a' | 'a.b' | 'a.b.c' */ export type NestedPaths = { [K in keyof T]: Required[K] extends GenericObject ? NestedPaths[K], Union, Join> : Union, Join>; }[keyof T]; /** * TypeFromPath * Get the type of the element specified by the path * @example * type TypeOfAB = TypeFromPath<{ a: { b: { c: string } }, 'a.b'> * // { c: string } */ export type TypeFromPath = { [K in Path]: K extends keyof T ? T[K] : K extends `${infer P}.${infer S}` ? T[P] extends GenericObject ? TypeFromPath : never : never; }[Path]; export {};