import { EqualsAnyOfUnion, IsFullStringLiteral } from './Equals.js'; /** * Joins two keys into a dot notation path * * Stops at arrays. Otherwise it would include `${number}` */ type Join = K extends string ? P extends string ? IsFullStringLiteral

extends true ? `${K}.${P}` : K : P extends number ? K : 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[]]; /** * All possible Object Paths, branches AND leaves — does NOT go deeper in optional props * @example OPathsWithoutOptional<{ a: { b: number }, x?: { y?: number } }> * // returns 'a' | 'a.b' | 'x' */ export type OPathsWithoutOptional = [D] extends [never] ? never : EqualsAnyOfUnion extends 1 ? '' : T extends { [key: string]: any; } ? { [K in keyof T]-?: K extends string ? `${K}` | Join> : never; }[keyof T] : ''; /** * All possible Object Paths, branches AND leaves— DOES go deeper in optional props * @example OPathsWithOptional<{ a: { b: number }, x?: { y?: number } }> * // returns 'a' | 'a.b' | 'x' | 'x.y' */ export type OPathsWithOptional = [D] extends [never] ? never : T extends { [key: string]: any; } ? Exclude<{ [K in keyof T]: K extends string ? `${K}` | Join> : never; }[keyof T], undefined> : ''; /** * All possible Object Paths, but only the leaves * @example OPaths<{ a: { b: number } }> * // returns 'a.b' */ export type OLeaves = [D] extends [never] ? '' : EqualsAnyOfUnion extends 1 ? '' : T extends { [key: string]: any; } ? { [K in keyof T]-?: IsFullStringLiteral extends true ? Join> : ''; }[keyof T] : ''; export {};