1
1
import { expectTypeOf } from 'vitest'
2
- import type { DeepKeys , DeepValue } from '../src/index'
2
+ import type { DeepKeys , DeepKeysOfType , DeepValue } from '../src/index'
3
3
4
4
/**
5
5
* Properly recognizes that `0` is not an object and should not have subkeys
6
6
*/
7
- type TupleSupport = DeepKeys < { topUsers : [ User , 0 , User ] } >
8
- expectTypeOf ( 0 as never as TupleSupport ) . toEqualTypeOf <
7
+ type TupleSupport = { topUsers : [ User , 0 , User ] }
8
+ expectTypeOf ( 0 as never as DeepKeys < TupleSupport > ) . toEqualTypeOf <
9
9
| 'topUsers'
10
10
| 'topUsers[0]'
11
11
| 'topUsers[0].name'
@@ -17,50 +17,95 @@ expectTypeOf(0 as never as TupleSupport).toEqualTypeOf<
17
17
| 'topUsers[2].id'
18
18
| 'topUsers[2].age'
19
19
> ( )
20
+ expectTypeOf ( 0 as never as DeepKeysOfType < TupleSupport , number > ) . toEqualTypeOf <
21
+ 'topUsers[0].age' | 'topUsers[1]' | 'topUsers[2].age'
22
+ > ( )
23
+ expectTypeOf ( 0 as never as DeepKeysOfType < TupleSupport , string > ) . toEqualTypeOf <
24
+ 'topUsers[0].name' | 'topUsers[0].id' | 'topUsers[2].name' | 'topUsers[2].id'
25
+ > ( )
26
+ expectTypeOf ( 0 as never as DeepKeysOfType < TupleSupport , User > ) . toEqualTypeOf <
27
+ 'topUsers[0]' | 'topUsers[2]'
28
+ > ( )
29
+ expectTypeOf (
30
+ 0 as never as DeepKeysOfType < TupleSupport , Date > ,
31
+ ) . toEqualTypeOf < never > ( )
20
32
21
33
/**
22
34
* Properly recognizes that a normal number index won't cut it and should be `[number]` prefixed instead
23
35
*/
24
- type ArraySupport = DeepKeys < { users : User [ ] } >
25
- expectTypeOf ( 0 as never as ArraySupport ) . toEqualTypeOf <
36
+ type ArraySupport = { users : User [ ] }
37
+ expectTypeOf ( 0 as never as DeepKeys < ArraySupport > ) . toEqualTypeOf <
26
38
| 'users'
27
39
| `users[${number } ]`
28
40
| `users[${number } ].name`
29
41
| `users[${number } ].id`
30
42
| `users[${number } ].age`
31
43
> ( )
44
+ expectTypeOf (
45
+ 0 as never as DeepKeysOfType < ArraySupport , number > ,
46
+ ) . toEqualTypeOf < `users[${number } ].age`> ( )
47
+ expectTypeOf ( 0 as never as DeepKeysOfType < ArraySupport , string > ) . toEqualTypeOf <
48
+ `users[${number } ].name` | `users[${number } ].id`
49
+ > ( )
50
+ expectTypeOf (
51
+ 0 as never as DeepKeysOfType < ArraySupport , User > ,
52
+ ) . toEqualTypeOf < `users[${number } ]`> ( )
53
+ expectTypeOf (
54
+ 0 as never as DeepKeysOfType < ArraySupport , Date > ,
55
+ ) . toEqualTypeOf < never > ( )
32
56
33
57
/**
34
58
* Properly handles deep object nesting like so:
35
59
*/
36
- type NestedSupport = DeepKeys < { meta : { mainUser : User } } >
37
- expectTypeOf ( 0 as never as NestedSupport ) . toEqualTypeOf <
60
+ type NestedSupport = { meta : { mainUser : User } }
61
+ expectTypeOf ( 0 as never as DeepKeys < NestedSupport > ) . toEqualTypeOf <
38
62
| 'meta'
39
63
| 'meta.mainUser'
40
64
| 'meta.mainUser.name'
41
65
| 'meta.mainUser.id'
42
66
| 'meta.mainUser.age'
43
67
> ( )
68
+ expectTypeOf (
69
+ 0 as never as DeepKeysOfType < NestedSupport , number > ,
70
+ ) . toEqualTypeOf < `meta.mainUser.age`> ( )
71
+ expectTypeOf ( 0 as never as DeepKeysOfType < NestedSupport , string > ) . toEqualTypeOf <
72
+ `meta.mainUser.name` | `meta.mainUser.id`
73
+ > ( )
74
+ expectTypeOf (
75
+ 0 as never as DeepKeysOfType < NestedSupport , User > ,
76
+ ) . toEqualTypeOf < `meta.mainUser`> ( )
77
+ expectTypeOf (
78
+ 0 as never as DeepKeysOfType < NestedSupport , Date > ,
79
+ ) . toEqualTypeOf < never > ( )
44
80
45
81
/**
46
82
* Properly handles deep partial object nesting like so:
47
83
*/
48
- type NestedPartialSupport = DeepKeys < { meta ?: { mainUser ?: User } } >
49
- expectTypeOf ( 0 as never as NestedPartialSupport ) . toEqualTypeOf <
84
+ type NestedPartialSupport = { meta ?: { mainUser ?: User } }
85
+ expectTypeOf ( 0 as never as DeepKeys < NestedPartialSupport > ) . toEqualTypeOf <
50
86
| 'meta'
51
87
| 'meta.mainUser'
52
88
| 'meta.mainUser.name'
53
89
| 'meta.mainUser.id'
54
90
| 'meta.mainUser.age'
55
91
> ( )
92
+ expectTypeOf (
93
+ 0 as never as DeepKeysOfType < NestedPartialSupport , number > ,
94
+ ) . toEqualTypeOf < never > ( )
95
+ expectTypeOf (
96
+ 0 as never as DeepKeysOfType < NestedPartialSupport , number | undefined > ,
97
+ ) . toEqualTypeOf < 'meta.mainUser.age' > ( )
56
98
57
99
/**
58
100
* Properly handles `object` edgecase nesting like so:
59
101
*/
60
- type ObjectNestedEdgecase = DeepKeys < { meta : { mainUser : object } } >
61
- expectTypeOf ( 0 as never as ObjectNestedEdgecase ) . toEqualTypeOf (
102
+ type ObjectNestedEdgecase = { meta : { mainUser : object } }
103
+ expectTypeOf ( 0 as never as DeepKeys < ObjectNestedEdgecase > ) . toEqualTypeOf (
62
104
0 as never as 'meta' | 'meta.mainUser' | `meta.mainUser.${string } `,
63
105
)
106
+ expectTypeOf (
107
+ 0 as never as DeepKeysOfType < ObjectNestedEdgecase , object > ,
108
+ ) . toEqualTypeOf < 'meta' | 'meta.mainUser' > ( )
64
109
65
110
/**
66
111
* Properly handles `object` edgecase like so:
@@ -71,10 +116,13 @@ expectTypeOf(0 as never as ObjectEdgecase).toEqualTypeOf<string>()
71
116
/**
72
117
* Properly handles `object` edgecase nesting like so:
73
118
*/
74
- type UnknownNestedEdgecase = DeepKeys < { meta : { mainUser : unknown } } >
119
+ type UnknownNestedEdgecase = { meta : { mainUser : unknown } }
75
120
expectTypeOf (
76
121
0 as never as 'meta' | 'meta.mainUser' | `meta.mainUser.${string } `,
77
- ) . toEqualTypeOf ( 0 as never as UnknownNestedEdgecase )
122
+ ) . toEqualTypeOf ( 0 as never as DeepKeys < UnknownNestedEdgecase > )
123
+ expectTypeOf (
124
+ 0 as never as DeepKeysOfType < UnknownNestedEdgecase , object > ,
125
+ ) . toEqualTypeOf < 'meta' > ( )
78
126
79
127
/**
80
128
* Properly handles discriminated unions like so:
@@ -83,10 +131,15 @@ type DiscriminatedUnion = { name: string } & (
83
131
| { variant : 'foo' }
84
132
| { variant : 'bar' ; baz : boolean }
85
133
)
86
- type DiscriminatedUnionKeys = DeepKeys < DiscriminatedUnion >
87
- expectTypeOf ( 0 as never as DiscriminatedUnionKeys ) . toEqualTypeOf <
134
+ expectTypeOf ( 0 as never as DeepKeys < DiscriminatedUnion > ) . toEqualTypeOf <
88
135
'name' | 'variant' | 'baz'
89
136
> ( )
137
+ expectTypeOf (
138
+ 0 as never as DeepKeysOfType < DiscriminatedUnion , string > ,
139
+ ) . toEqualTypeOf < 'name' | 'variant' > ( )
140
+ expectTypeOf (
141
+ 0 as never as DeepKeysOfType < DiscriminatedUnion , boolean > ,
142
+ ) . toEqualTypeOf < 'baz' > ( )
90
143
91
144
type DiscriminatedUnionValueShared = DeepValue < DiscriminatedUnion , 'variant' >
92
145
expectTypeOf ( 0 as never as DiscriminatedUnionValueShared ) . toEqualTypeOf <
@@ -98,10 +151,16 @@ expectTypeOf(
98
151
) . toEqualTypeOf < boolean > ( )
99
152
100
153
/**
101
- * Properly handles `object ` edgecase like so:
154
+ * Properly handles `unknown ` edgecase like so:
102
155
*/
103
156
type UnknownEdgecase = DeepKeys < unknown >
104
157
expectTypeOf ( 0 as never as UnknownEdgecase ) . toEqualTypeOf < string > ( )
158
+ expectTypeOf (
159
+ 0 as never as DeepKeysOfType < unknown , unknown > ,
160
+ ) . toEqualTypeOf < string > ( )
161
+ expectTypeOf (
162
+ 0 as never as DeepKeysOfType < unknown , object > ,
163
+ ) . toEqualTypeOf < never > ( )
105
164
106
165
type NestedKeysExample = DeepValue <
107
166
{ meta : { mainUser : User } } ,
@@ -364,10 +423,16 @@ type ObjectWithAny = {
364
423
}
365
424
}
366
425
367
- type AnyObjectKeys = DeepKeys < ObjectWithAny >
368
- expectTypeOf ( 0 as never as AnyObjectKeys ) . toEqualTypeOf <
426
+ expectTypeOf ( 0 as never as DeepKeys < ObjectWithAny > ) . toEqualTypeOf <
369
427
'a' | 'b' | 'obj' | `a.${string } ` | 'obj.c' | `obj.c.${string } ` | 'obj.d'
370
428
> ( )
429
+ // since any can also be number, It's okay to be included
430
+ expectTypeOf ( 0 as never as DeepKeysOfType < ObjectWithAny , number > ) . toEqualTypeOf <
431
+ 'a' | 'b' | 'obj.c' | 'obj.d'
432
+ > ( )
433
+ expectTypeOf ( 0 as never as DeepKeysOfType < ObjectWithAny , string > ) . toEqualTypeOf <
434
+ 'a' | 'obj.c'
435
+ > ( )
371
436
type AnyObjectExample = DeepValue < ObjectWithAny , 'a' >
372
437
expectTypeOf ( 0 as never as AnyObjectExample ) . toEqualTypeOf < any > ( )
373
438
type AnyObjectExample2 = DeepValue < ObjectWithAny , 'b' >
0 commit comments