@@ -21,42 +21,164 @@ expectType<{a: number; b?: {c?: string}}>(variation4);
2121declare const variation5 : SetRequiredDeep < { a ?: '1' ; b ?: { c ?: boolean } } | { a ?: '2' ; b ?: { c ?: boolean } } , 'a' > ;
2222expectType < { a : '1' ; b ?: { c ?: boolean } } | { a : '2' ; b ?: { c ?: boolean } } > ( variation5 ) ;
2323
24- // Set array key to required
24+ // Set key with array type to required
2525declare const variation6 : SetRequiredDeep < { a ?: Array < { b ?: number } > } , 'a' > ;
2626expectType < { a : Array < { b ?: number } > } > ( variation6 ) ;
2727
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-
3628// 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 ) ;
3931
4032// 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 ) ;
4335
4436// 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 ) ;
4743
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 ) ;
5149
5250// Works with number keys
5351declare const variation13 : SetRequiredDeep < { 0 : 1 ; 1 : { 2 ?: string } } , '1.2' > ;
5452expectType < { 0 : 1 ; 1 : { 2 : string } } > ( variation13 ) ;
5553
54+ declare const variation14 : SetRequiredDeep < { 0 ?: 1 ; 1 ?: { 2 ?: string } } , 0 | 1 > ;
55+ expectType < { 0 : 1 ; 1 : { 2 ?: string } } > ( variation14 ) ;
56+
5657// 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 ) ;
5960
6061// 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