import { ApplyDefaultOptions, OverWritable } from "./_internal"; import { And } from "./and"; import { ArrayElementType } from "./array-element-type"; import { IsEqual } from "./equal"; import { Increment } from "./increment"; import { IsArrayIndex } from "./is-array-index"; import { IsTuple } from "./is-tuple"; import { Join } from "./join"; import { IsNever } from "./never"; import { ValueOf, ValueOfArray } from "./value-of"; export type PathToFieldsOptions = OverWritable & { ignoredTypes?: unknown; stopTypes?: unknown; limit?: number; format?: "dot" | "array"; ignoredKeys?: PropertyKey; arrayIndexing?: { exactIndexes: boolean; }; }; export type DefaultPathToFieldsOptions = { ignoredTypes: never; stopTypes: string | number | boolean | symbol | Date | Function; format: "dot"; limit: 10; ignoredKeys: never; arrayIndexing: { exactIndexes: false; }; }; type OverwriteRules = { limit: true; format: true; arrayIndexing: { exactIndexes: true; }; }; type _PathToFieldsArray< T extends readonly unknown[], Options extends PathToFieldsOptions, Iteration extends number = 0 > = And< IsTuple, IsEqual > extends true ? ValueOfArray<{ [K in keyof T]: IsArrayIndex extends true ? [K, ..._PathToFields>] : never; }> : ArrayElementType extends infer ElementType ? [ `${number}`, ...(ElementType extends ElementType ? _PathToFields> : never) ] : never; type _PathToFields< T, Options extends PathToFieldsOptions, Iteration extends number = 0 > = T extends Options["ignoredTypes"] ? never : T extends Options["stopTypes"] ? [] : IsEqual extends true ? never : T extends readonly unknown[] ? _PathToFieldsArray : ValueOf<{ [K in Exclude]: NonNullable< T[K] > extends infer NonNullableFields ? NonNullableFields extends readonly unknown[] ? [K, ..._PathToFieldsArray] : [ K, ..._PathToFields> ] : never; }>; /** * Get all possible paths to fields in an object * @example * ```ts * // "a" | "b" | "d" * type T0 = PathToFields<{a: string, b: number, d: boolean}>; * // ["arr.0.a", "arr.0.b", "arr.1.c"] * type T1 = PathToFields<{arr: [{a: string; b: number}, {c: boolean}]}, { * arrayIndexing: { * exactIndexes: true; * } * }>; * ``` */ export type PathToFields< T, Options extends PathToFieldsOptions & { overwriteDefault?: boolean } = never > = ( IsNever extends true ? DefaultPathToFieldsOptions : ApplyDefaultOptions< Omit, Options, DefaultPathToFieldsOptions, OverwriteRules, PathToFieldsOptions["overwriteDefault"] > ) extends infer MergedOptions extends PathToFieldsOptions ? _PathToFields extends infer Paths extends readonly ( | string | number )[] ? IsEqual extends true ? Paths extends Paths ? Join : never : Paths : never : never;