11import type { UnknownArray } from './unknown-array.d.ts' ;
22import type { LiteralUnion } from './literal-union.d.ts' ;
33import type { EmptyObject } from './empty-object.d.ts' ;
4- import type { GreaterThan } from './greater-than.d.ts' ;
54import type { Subtract } from './subtract.d.ts' ;
65import type { IsNever } from './is-never.d.ts' ;
76import type { IsAny } from './is-any.d.ts' ;
@@ -194,14 +193,13 @@ open('listB.1'); // TypeError. Because listB only has one element.
194193export type Paths < T , Options extends PathsOptions = { } > = _Paths < T , ApplyDefaultOptions < PathsOptions , DefaultPathsOptions , Options > > ;
195194
196195type _Paths < T , Options extends Required < PathsOptions > > =
197- T extends NonRecursiveType | ReadonlyMap < unknown , unknown > | ReadonlySet < unknown >
198- ? never
199- : IsAny < T > extends true
200- ? never
196+ T extends NonRecursiveType | ReadonlyMap < unknown , unknown > | ReadonlySet < unknown > ? never
197+ : IsAny < T > extends true ? never
201198 : T extends UnknownArray
202199 ? number extends T [ 'length' ]
203- // We need to handle the fixed and non-fixed index part of the array separately.
204- ? InternalPaths < StaticPartOfArray < T > , Options > | InternalPaths < Array < VariablePartOfArray < T > [ number ] > , Options >
200+ ? // We need to handle the fixed and non-fixed index part of the array separately.
201+ | InternalPaths < StaticPartOfArray < T > , Options > // ! Should this be updated to use `ExcludeRestElement`.
202+ | InternalPaths < Array < VariablePartOfArray < T > [ number ] > , Options > // ! And this to use `ExtractRestElement`.
205203 : InternalPaths < T , Options >
206204 : T extends object
207205 ? InternalPaths < T , Options >
@@ -211,53 +209,49 @@ type InternalPaths<T, Options extends Required<PathsOptions>> =
211209 Options [ 'maxRecursionDepth' ] extends infer MaxDepth extends number
212210 ? Required < T > extends infer T
213211 ? IsNever < keyof T > extends true
214- ? never // Ignore empty array/object
212+ ? never // Ignore empty array/object and not index signature types (e.g, `Record<string, 'foo'>`).
215213 : {
216- [ Key in keyof T ] :
217- Key extends PathableKeys // Limit `Key` to string or number.
218- ? (
219- Options [ 'bracketNotation' ] extends true
220- ? IsNumberLike < Key > extends true
221- ? `[${Key } ]`
222- : ( Key | ToString < Key > )
223- : ( Key | ToString < Key > ) // If `Key` is a number, return `Key | `${Key}``, because both `array[0]` and `array['0']` work.
214+ [ Key in keyof T ] : Key extends PathableKeys // Limit `Key` to string or number.
215+ ? ( Options [ 'bracketNotation' ] extends true
216+ ? IsNumberLike < Key > extends true
217+ ? `[${Key } ]`
218+ : ( Key | ToString < Key > )
219+ : ( Key | ToString < Key > ) // If `Key` is a number, return `Key | `${Key}``, because both `array[0]` and `array['0']` work.
224220 ) extends infer TranformedKey extends PathableKeys ?
225221 // 1. If style is 'a[0].b' and 'Key' is a numberlike value like 3 or '3', transform 'Key' to `[${Key}]`, else to `${Key}` | Key
226222 // 2. If style is 'a.0.b', transform 'Key' to `${Key}` | Key
227- | ( ( Options [ 'leavesOnly' ] extends true
228- ? MaxDepth extends 0
229- ? TranformedKey
230- : T [ Key ] extends EmptyObject | EmptyArray | NonRecursiveType | ReadonlyMap < unknown , unknown > | ReadonlySet < unknown >
223+ (
224+ ( Options [ 'leavesOnly' ] extends true
225+ ? MaxDepth extends 0
231226 ? TranformedKey
227+ : T [ Key ] extends EmptyObject | EmptyArray | NonRecursiveType | ReadonlyMap < unknown , unknown > | ReadonlySet < unknown >
228+ ? TranformedKey
229+ : never
230+ : TranformedKey
231+ ) extends infer _TransformedKey
232+ // If `depth` is provided, the condition becomes truthy only when it reaches `0`.
233+ // Otherwise, since `depth` defaults to `number`, the condition is always truthy, returning paths at all depths.
234+ ? 0 extends Options [ 'depth' ]
235+ ? string extends _TransformedKey // TODO: Replace with `IsStringPrimitive` when approved.
236+ ? LiteralUnion < never , string > // Prevent returning `string`, instead returns `(string & {})`.
237+ : _TransformedKey
232238 : never
233- : TranformedKey
234- ) extends infer _TransformedKey
235- // If `depth` is provided, the condition becomes truthy only when it reaches `0`.
236- // Otherwise, since `depth` defaults to `number`, the condition is always truthy, returning paths at all depths.
237- ? 0 extends Options [ 'depth' ]
238- ? string extends _TransformedKey // TODO: Replace with `IsStringPrimitive` when approved.
239- ? LiteralUnion < never , string > // Prevent returning `string`.
240- : _TransformedKey
241239 : never
242- : never )
243- | (
240+ ) | (
244241 // Recursively generate paths for the current key
245- GreaterThan < MaxDepth , 0 > extends true // Limit the depth to prevent infinite recursion
246- ? _Paths < T [ Key ] , {
242+ MaxDepth extends 0 ? never // Limit the depth to prevent infinite recursion
243+ : _Paths < T [ Key ] , {
247244 bracketNotation : Options [ 'bracketNotation' ] ;
248245 maxRecursionDepth : Subtract < MaxDepth , 1 > ;
249246 depth : Subtract < Options [ 'depth' ] , 1 > ;
250247 leavesOnly : Options [ 'leavesOnly' ] ;
251- } > extends infer SubPath
252- ? SubPath extends PathableKeys
253- ? Options [ 'bracketNotation' ] extends true
254- ? SubPath extends `[${PathableKeys } ]${string } `
255- ? `${TranformedKey } ${SubPath } ` // If next node is number key like `[3]`, no need to add `.` before it.
256- : `${TranformedKey } .${SubPath } `
248+ } > extends infer SubPath extends PathableKeys
249+ ? Options [ 'bracketNotation' ] extends true
250+ ? SubPath extends `[${PathableKeys } ]${string } ` // Check if its a bracket notation.
251+ ? `${TranformedKey } ${SubPath } ` // If next node is number key like `[3]`, no need to add `.` before it.
257252 : `${TranformedKey } .${SubPath } `
258- : never
253+ : `${ TranformedKey } .${ SubPath } `
259254 : never
260- : never
261255 )
262256 : never
263257 : never
0 commit comments