@@ -526,13 +526,57 @@ declare const indexSignatureDepthLeaves: Paths<{a: {[x: string]: {b: string; c:
526526expectType < `a.${string } .b` | `a.${string } .c` | 'd' > ( indexSignatureDepthLeaves ) ;
527527
528528// Generic types
529- type SomeTypeWithConstraint < T , _U extends Paths < T > > = never ;
529+ type PathsConstraint < T , _U extends Paths < T > > = never ;
530530
531- type Foo < T > = { bar : { baz : T } } ;
532- type Test1 < T > = SomeTypeWithConstraint < Foo < T > , 'bar.baz' > ;
531+ type Generic1 < T > = { bar : { baz : T } } ;
532+ type Test1 < T > = PathsConstraint < Generic1 < T > , 'bar.baz' > ;
533533
534- type Bar < T , U > = { bar : { baz : { qux : T } ; fizz : { buzz : U } | U | T } } ;
535- type Test2 < T , U > = SomeTypeWithConstraint <
536- Bar < T , U > ,
534+ type Generic2 < T , U > = { bar : { baz : { qux : T } ; fizz : { buzz : U } | U | T } } ;
535+ type Test2 < T , U > = PathsConstraint <
536+ Generic2 < T , U > ,
537537 'bar' | 'bar.baz' | 'bar.baz.qux' | 'bar.fizz' | 'bar.fizz.buzz'
538538> ;
539+
540+ type LeavesOnlyPathsConstraint < T , _U extends Paths < T , { leavesOnly : true } > > = never ;
541+
542+ type Generic3 < T > = { bar : { baz : T ; qux : string } } ;
543+ type Test3 < T > = LeavesOnlyPathsConstraint < Generic3 < T > , 'bar.qux' > ;
544+ // @ts -expect-error
545+ type Test4 < T > = LeavesOnlyPathsConstraint < Generic3 < T > , 'bar' > ; // 'bar' is not a leaf
546+ // @ts -expect-error
547+ type Test5 < T > = LeavesOnlyPathsConstraint < Generic3 < T > , 'bar.baz' > ; // 'bar.baz' is not a leaf, because `T` is not known.
548+
549+ type DepthPathsConstraint < T , _U extends Paths < T , { depth : 1 } > > = never ;
550+
551+ type Generic4 < T > = { bar : { baz : T } ; qux : [ T ] } ;
552+ type Test6 < T > = DepthPathsConstraint < Generic4 < T > , 'bar.baz' | 'qux.0' > ;
553+ // @ts -expect-error
554+ type Test7 < T > = DepthPathsConstraint < Generic4 < T > , 'bar' > ; // 'bar' is not at depth `1`
555+ // @ts -expect-error
556+ type Test8 < T > = DepthPathsConstraint < Generic4 < T > , 'qux' > ; // 'qux' is not at depth `1`
557+
558+ type BracketNotationPathsConstraint < T , _U extends Paths < T , { bracketNotation : true } > > = never ;
559+
560+ type Generic5 < T > = { 1 : { 2 : T } ; 3 : [ T ] } ;
561+ type Test9 < T > = BracketNotationPathsConstraint < Generic5 < T > , '[1]' | '[1][2]' | '[3]' | '[3][0]' > ;
562+
563+ type MaxRecursionDepthPathsConstraint < T , _U extends Paths < T , { maxRecursionDepth : 2 } > > = never ;
564+
565+ type Generic6 < T > = { foo : { bar : T } ; baz : T ; fizz : { buzz : { qux : { quxx : T } } } } ;
566+ type Test10 < T > = MaxRecursionDepthPathsConstraint <
567+ Generic6 < T > ,
568+ 'foo' | 'foo.bar' | 'baz' | 'fizz' | 'fizz.buzz' | 'fizz.buzz.qux'
569+ > ;
570+ // @ts -expect-error
571+ type Test11 < T > = MaxRecursionDepthPathsConstraint < Generic6 < T > , 'fizz.buzz.qux.quxx' > ; // 'fizz.buzz.qux.quxx' is at depth `3`
572+
573+ type LeavesOnlyAndDepthPathsConstraint < T , _U extends Paths < T , { leavesOnly : true ; depth : 1 } > > = never ;
574+
575+ type Generic7 < T > = { foo : { bar : T ; baz : string ; fizz : { buzz : number } } ; qux : string } ;
576+ type Test12 < T > = LeavesOnlyAndDepthPathsConstraint < Generic7 < T > , 'foo.baz' > ;
577+ // @ts -expect-error
578+ type Test13 < T > = LeavesOnlyAndDepthPathsConstraint < Generic7 < T > , 'qux' > ; // 'qux' is a leaf, but not at depth `1`.
579+ // @ts -expect-error
580+ type Test14 < T > = LeavesOnlyAndDepthPathsConstraint < Generic7 < T > , 'foo.fizz' > ; // 'foo.fizz' is at depth `1`, but not a leaf.
581+ // @ts -expect-error
582+ type Test15 < T > = LeavesOnlyAndDepthPathsConstraint < Generic7 < T > , 'foo.bar' > ; // 'foo.bar' is at depth `1`, but not a leaf because `T` is not known.
0 commit comments