@@ -21,42 +21,164 @@ expectType<{a: number; b?: {c?: string}}>(variation4);
21
21
declare const variation5 : SetRequiredDeep < { a ?: '1' ; b ?: { c ?: boolean } } | { a ?: '2' ; b ?: { c ?: boolean } } , 'a' > ;
22
22
expectType < { a : '1' ; b ?: { c ?: boolean } } | { a : '2' ; b ?: { c ?: boolean } } > ( variation5 ) ;
23
23
24
- // Set array key to required
24
+ // Set key with array type to required
25
25
declare const variation6 : SetRequiredDeep < { a ?: Array < { b ?: number } > } , 'a' > ;
26
26
expectType < { a : Array < { b ?: number } > } > ( variation6 ) ;
27
27
28
- // Set key inside array to required
29
- declare const variation7 : SetRequiredDeep < { a ?: Array < { b ?: number } > } , `a.${number } .b`> ;
30
- expectType < { a ?: Array < { b : number } > } > ( variation7 ) ;
31
-
32
- // Set only specified keys inside array to required
33
- declare const variation8 : SetRequiredDeep < { a ?: Array < { b ?: number ; c ?: string } > } , `a.${number } .b`> ;
34
- expectType < { a ?: Array < { b : number ; c ?: string } > } > ( variation8 ) ;
35
-
36
28
// Can set both root and nested keys to required
37
- declare const variation9 : SetRequiredDeep < { a ?: number ; b ?: { c ?: string } } , 'b' | 'b.c' > ;
38
- expectType < { a ?: number ; b : { c : string } } > ( variation9 ) ;
29
+ declare const variation7 : SetRequiredDeep < { a ?: number ; b ?: { c ?: string } } , 'b' | 'b.c' > ;
30
+ expectType < { a ?: number ; b : { c : string } } > ( variation7 ) ;
39
31
40
32
// Preserves required root keys
41
- declare const variation10 : SetRequiredDeep < { a : 1 ; b : { c ?: 1 } } , 'b.c' > ;
42
- expectType < { a : 1 ; b : { c : 1 } } > ( variation10 ) ;
33
+ declare const variation8 : SetRequiredDeep < { a : 1 ; b : { c ?: 1 } } , 'b.c' > ;
34
+ expectType < { a : 1 ; b : { c : 1 } } > ( variation8 ) ;
43
35
44
36
// Preserves union in root keys
45
- declare const variation11 : SetRequiredDeep < { a : 1 ; b : { c ?: 1 } | number } , 'b.c' > ;
46
- expectType < { a : 1 ; b : { c : 1 } | number } > ( variation11 ) ;
37
+ declare const variation9 : SetRequiredDeep < { a : 1 ; b : { c ?: 1 } | number } , 'b.c' > ;
38
+ expectType < { a : 1 ; b : { c : 1 } | number } > ( variation9 ) ;
39
+
40
+ // Preserves readonly
41
+ declare const variation10 : SetRequiredDeep < { a : 1 ; readonly b : { c ?: 1 } } , 'b.c' > ;
42
+ expectType < { a : 1 ; readonly b : { c : 1 } } > ( variation10 ) ;
47
43
48
- // Preserves readonly in root keys
49
- declare const variation12 : SetRequiredDeep < { a : 1 ; readonly b : { c ?: 1 } } , 'b.c' > ;
50
- expectType < { a : 1 ; readonly b : { c : 1 } } > ( variation12 ) ;
44
+ declare const variation11 : SetRequiredDeep < { readonly a ?: 1 ; readonly b ?: { readonly c ?: 1 } } , 'a' | 'b' > ;
45
+ expectType < { readonly a : 1 ; readonly b : { readonly c ?: 1 } } > ( variation11 ) ;
46
+
47
+ declare const variation12 : SetRequiredDeep < { readonly a ?: 1 ; readonly b ?: { readonly c ?: 1 } } , 'a' | 'b' | 'b.c' > ;
48
+ expectType < { readonly a : 1 ; readonly b : { readonly c : 1 } } > ( variation12 ) ;
51
49
52
50
// Works with number keys
53
51
declare const variation13 : SetRequiredDeep < { 0 : 1 ; 1 : { 2 ?: string } } , '1.2' > ;
54
52
expectType < { 0 : 1 ; 1 : { 2 : string } } > ( variation13 ) ;
55
53
54
+ declare const variation14 : SetRequiredDeep < { 0 ?: 1 ; 1 ?: { 2 ?: string } } , 0 | 1 > ;
55
+ expectType < { 0 : 1 ; 1 : { 2 ?: string } } > ( variation14 ) ;
56
+
56
57
// Multiple keys
57
- declare const variation14 : SetRequiredDeep < { a ?: 1 ; b ?: { c ?: 2 } ; d ?: { e ?: { f ?: 2 } ; g ?: 3 } } , 'a' | 'b' | 'b.c' | 'd.e.f' | 'd.g' > ;
58
- expectType < { a : 1 ; b : { c : 2 } ; d ?: { e ?: { f : 2 } ; g : 3 } } > ( variation14 ) ;
58
+ declare const variation15 : SetRequiredDeep < { a ?: 1 ; b ?: { c ?: 2 } ; d ?: { e ?: { f ?: 2 } ; g ?: 3 } } , 'a' | 'b' | 'b.c' | 'd.e.f' | 'd.g' > ;
59
+ expectType < { a : 1 ; b : { c : 2 } ; d ?: { e ?: { f : 2 } ; g : 3 } } > ( variation15 ) ;
59
60
60
61
// Index signatures
61
- declare const variation15 : SetRequiredDeep < { [ x : string ] : any ; a ?: number ; b ?: { c ?: number } } , 'a' | 'b.c' > ;
62
- expectType < { [ x : string ] : any ; a : number ; b ?: { c : number } } > ( variation15 ) ;
62
+ declare const variation16 : SetRequiredDeep < { [ x : string ] : any ; a ?: number ; b ?: { c ?: number } } , 'a' | 'b.c' > ;
63
+ expectType < { [ x : string ] : any ; a : number ; b ?: { c : number } } > ( variation16 ) ;
64
+
65
+ // Preserves union in nested keys
66
+ declare const variation17 : SetRequiredDeep < { a : 1 ; b ?: { c ?: 1 } | number } , 'b' > ;
67
+ expectType < { a : 1 ; b : { c ?: 1 } | number } > ( variation17 ) ;
68
+
69
+ declare const variation18 : SetRequiredDeep < { a ?: number ; b ?: { c ?: number } | { d ?: string } } , 'b' | 'b.d' > ;
70
+ expectType < { a ?: number ; b : { c ?: number } | { d : string } } > ( variation18 ) ;
71
+
72
+ // Works with number keys containing dots
73
+ // NOTE: Passing "1.2" instead of 1.2 will treat it as a path instead of a key
74
+ declare const variation19 : SetRequiredDeep < { 1.2 ?: string ; 1 ?: { 2 ?: string } } , 1.2 > ;
75
+ expectType < { 1.2 : string ; 1 ?: { 2 ?: string } } > ( variation19 ) ;
76
+
77
+ declare const variation20 : SetRequiredDeep < { 1.2 ?: string ; 1 ?: { 2 ?: string } } , '1.2' > ;
78
+ expectType < { 1.2 ?: string ; 1 ?: { 2 : string } } > ( variation20 ) ;
79
+
80
+ declare const variation21 : SetRequiredDeep < { 1.2 ?: string ; 1 ?: { 2 ?: string } } , 1.2 | '1.2' > ;
81
+ expectType < { 1.2 : string ; 1 ?: { 2 : string } } > ( variation21 ) ;
82
+
83
+ // Works with unions
84
+ declare const variation22 : SetRequiredDeep < { a ?: { readonly b ?: number } } | { readonly b ?: { c ?: number [ ] } } , 'a.b' | 'b' | 'b.c' > ;
85
+ expectType < { a ?: { readonly b : number } } | { readonly b : { c : number [ ] } } > ( variation22 ) ;
86
+
87
+ // Works with `KeyPaths` containing template literals
88
+ declare const variation23 : SetRequiredDeep < { a ?: number ; b ?: { c ?: number } | { d ?: number } } , `b.${'c' | 'd' } `> ;
89
+ expectType < { a ?: number ; b ?: { c : number } | { d : number } } > ( variation23 ) ;
90
+
91
+ declare const variation24 : SetRequiredDeep <
92
+ { a ?: number ; b ?: { readonly c ?: { 1 ?: number } } | { d ?: { 1 ?: number } } } , 'a' | `b.${'c' | 'd' } .1`
93
+ > ;
94
+ expectType < { a : number ; b ?: { readonly c ?: { 1 : number } } | { d ?: { 1 : number } } } > ( variation24 ) ;
95
+
96
+ // Calls `RequiredDeep` when `KeyPaths` is `any`
97
+ declare const variation25 : SetRequiredDeep < { a ?: number ; readonly b ?: { c ?: string } } , any > ;
98
+ expectType < { a : number ; readonly b : { c : string } } > ( variation25 ) ;
99
+
100
+ // Does nothing when `KeyPaths` is `never`
101
+ declare const variation26 : SetRequiredDeep < { a ?: number ; readonly b ?: { c ?: string } } , never > ;
102
+ expectType < { a ?: number ; readonly b ?: { c ?: string } } > ( variation26 ) ;
103
+
104
+ // =================
105
+ // Works with arrays
106
+ // =================
107
+
108
+ // All optional elements
109
+ expectType < { a ?: [ string , number , boolean ?] } > ( { } as SetRequiredDeep < { a ?: [ string ?, number ?, boolean ?] } , 'a.0' | 'a.1' > ) ;
110
+
111
+ // Mix of optional and required elements
112
+ expectType < { a : readonly [ string , number , boolean ] } > ( { } as SetRequiredDeep < { a : readonly [ string , number ?, boolean ?] } , 'a.1' | 'a.2' > ) ;
113
+
114
+ // Mix of optional and rest elements
115
+ expectType < { readonly a : [ string , number , boolean ?, ...number [ ] ] } > ( { } as SetRequiredDeep < { readonly a : [ string ?, number ?, boolean ?, ...number [ ] ] } , 'a.0' | 'a.1' > ) ;
116
+
117
+ // Mix of optional, required, and rest elements
118
+ expectType < { readonly a ?: [ string , number , boolean , ...string [ ] ] } > ( { } as SetRequiredDeep < { readonly a ?: [ string , number ?, boolean ?, ...string [ ] ] } , 'a.1' | 'a.2' > ) ;
119
+
120
+ // Works with readonly arrays
121
+ expectType < { a ?: { b ?: readonly [ ( string | number ) ] } } > ( { } as SetRequiredDeep < { a ?: { b ?: readonly [ ( string | number ) ?] } } , 'a.b.0' > ) ;
122
+ expectType < { a : readonly [ string , number , boolean , ...string [ ] ] } > (
123
+ { } as SetRequiredDeep < { a ?: readonly [ string , number ?, boolean ?, ...string [ ] ] } , 'a' | 'a.1' | 'a.2' > ,
124
+ ) ;
125
+
126
+ // Ignores `Keys` that are already required
127
+ expectType < { a : [ string , number ?, boolean ?] } > ( { } as SetRequiredDeep < { a : [ string , number ?, boolean ?] } , 'a.0' > ) ;
128
+
129
+ // Ignores `Keys` that are not known
130
+ // This case is only possible when the array contains a rest element,
131
+ // because otherwise the constaint on `KeyPaths` would disallow out of bound keys.
132
+ expectType < { a ?: readonly [ string ?, number ?, boolean ?, ...number [ ] ] } > (
133
+ { } as SetRequiredDeep < { a ?: readonly [ string ?, number ?, boolean ?, ...number [ ] ] } , 'a.10' > ,
134
+ ) ;
135
+
136
+ // Marks all keys as required, if `Keys` is `number`.
137
+ // This case is only possible when the array contains a rest element,
138
+ // because otherwise the constaint on `KeyPaths` would be stricter.
139
+ expectType < { a ?: readonly [ string , number , boolean , ...number [ ] ] } > (
140
+ { } as SetRequiredDeep < { a ?: readonly [ string ?, number ?, boolean ?, ...number [ ] ] } , `a.${number } `> ,
141
+ ) ;
142
+
143
+ // Preserves `| undefined`, similar to how built-in `Required` works.
144
+ expectType < { a : [ string | undefined , number | undefined , boolean ] } > ( { } as SetRequiredDeep < { a : [ string | undefined , ( number | undefined ) ?, boolean ?] } , 'a.0' | 'a.1' | 'a.2' > ) ;
145
+ expectType < { a : readonly [ string | undefined , ( number | undefined ) ?, boolean ?] } > (
146
+ { } as SetRequiredDeep < { a : readonly [ ( string | undefined ) ?, ( number | undefined ) ?, boolean ?] } , 'a.0' > ,
147
+ ) ;
148
+
149
+ // Optional elements cannot appear after required ones, `Keys` leading to such situations are ignored.
150
+ expectType < { a : [ string ?, number ?, boolean ?] } > ( { } as SetRequiredDeep < { a : [ string ?, number ?, boolean ?] } , 'a.1' | 'a.2' > ) ; // `a.1` and `a.2` can't be required when `a.0` is optional
151
+ expectType < { a : [ string , number , boolean ?, string ?, string ?] } > (
152
+ { } as SetRequiredDeep < { a : [ string ?, number ?, boolean ?, string ?, string ?] } , 'a.0' | 'a.1' | 'a.3' > , // `a.3` can't be required when `a.2` is optional
153
+ ) ;
154
+ expectType < { a : readonly [ string | undefined , number ?, boolean ?, ...string [ ] ] } > (
155
+ { } as SetRequiredDeep < { a ?: readonly [ string | undefined , number ?, boolean ?, ...string [ ] ] } , 'a' | 'a.2' > , // `a.2` can't be required when `a.1` is optional
156
+ ) ;
157
+
158
+ // Works with unions of arrays
159
+ expectType < { a : [ string ] | [ string , number , boolean ?, ...number [ ] ] | readonly [ string , number , boolean ?] } > (
160
+ { } as SetRequiredDeep < { a : [ string ?] | [ string , number ?, boolean ?, ...number [ ] ] | readonly [ string , number ?, boolean ?] } , 'a.0' | 'a.1' > ,
161
+ ) ;
162
+
163
+ // Works with labelled tuples
164
+ expectType < { a ?: [ b : string , c : number ] } > ( { } as SetRequiredDeep < { a ?: [ b ?: string , c ?: number ] } , 'a.0' | 'a.1' > ) ;
165
+
166
+ // Non tuple arrays are left unchanged
167
+ expectType < { a : string [ ] } > ( { } as SetRequiredDeep < { a : string [ ] } , `a.${number } `> ) ;
168
+ expectType < { readonly a : ReadonlyArray < string | number > } > ( { } as SetRequiredDeep < { readonly a ?: ReadonlyArray < string | number > } , 'a' | `a.${number } `> ) ;
169
+
170
+ // Works with nested arrays
171
+ expectType < { a ?: [ [ string , number ?] ?] } > ( { } as SetRequiredDeep < { a ?: [ [ string ?, number ?] ?] } , 'a.0.0' > ) ;
172
+ expectType < { a ?: [ [ string , number ] ] } > ( { } as SetRequiredDeep < { a ?: [ [ string ?, number ?] ?] } , 'a.0' | 'a.0.0' | 'a.0.1' > ) ;
173
+ expectType < { a ?: Array < [ string , number ?] > } > ( { } as SetRequiredDeep < { a ?: Array < [ string ?, number ?] > } , `a.${number } .0`> ) ;
174
+
175
+ // Set key inside array to required
176
+ expectType < { a ?: Array < { b : number } > } > ( { } as SetRequiredDeep < { a ?: Array < { b ?: number } > } , `a.${number } .b`> ) ;
177
+ expectType < { readonly a ?: [ { readonly b : number } ] } > ( { } as SetRequiredDeep < { readonly a ?: [ { readonly b ?: number } ] } , 'a.0.b' > ) ;
178
+ expectType < { readonly a : [ { readonly b : number } , { c ?: string } ] } > (
179
+ { } as SetRequiredDeep < { readonly a ?: [ { readonly b ?: number } , { c ?: string } ?] } , 'a' | 'a.0.b' | 'a.1' > ,
180
+ ) ;
181
+
182
+ // Set only specified keys inside array to required
183
+ expectType < { a ?: Array < { b : number ; c ?: string } > } > ( { } as SetRequiredDeep < { a ?: Array < { b ?: number ; c ?: string } > } , `a.${number } .b`> ) ;
184
+ expectType < { a : [ { b ?: number ; readonly c : string } ] } > ( { } as SetRequiredDeep < { a : [ { b ?: number ; readonly c ?: string } ] } , 'a.0.c' > ) ;
0 commit comments