@@ -27,11 +27,11 @@ const c4 = {};
2727const a4a = [ c4 , r4 ] ; // {}[]
2828const a4b = [ r4 , c4 ] ; // {}[]
2929
30- // Check that narrowing preserves original type in false branch for non-identical mutual subtypes
30+ // Check that {} is a strict supertype of Record<string, unknown>
3131
3232declare function isObject1 ( value : unknown ) : value is Record < string , unknown > ;
3333
34- function gg ( x : { } ) {
34+ function gg1 ( x : { } ) {
3535 if ( isObject1 ( x ) ) {
3636 x ; // Record<string, unknown>
3737 }
@@ -45,14 +45,40 @@ declare function isObject2(value: unknown): value is {};
4545
4646function gg2 ( x : Record < string , unknown > ) {
4747 if ( isObject2 ( x ) ) {
48- x ; // {}
48+ x ; // Record<string, unknown>
4949 }
5050 else {
51- x ; // Record<string, unknown>
51+ x ; // never
5252 }
5353 x ; // Record<string, unknown>
5454}
5555
56+ // Check that {} is a strict supertype of Record<string, any>
57+
58+ declare function isObject3 ( value : unknown ) : value is Record < string , any > ;
59+
60+ function gg3 ( x : { } ) {
61+ if ( isObject3 ( x ) ) {
62+ x ; // Record<string, any>
63+ }
64+ else {
65+ x ; // {}
66+ }
67+ x ; // {}
68+ }
69+
70+ declare function isObject4 ( value : unknown ) : value is { } ;
71+
72+ function gg4 ( x : Record < string , any > ) {
73+ if ( isObject4 ( x ) ) {
74+ x ; // Record<string, any>
75+ }
76+ else {
77+ x ; // never
78+ }
79+ x ; // Record<string, any>
80+ }
81+
5682// Repro from #50916
5783
5884type Identity < T > = { [ K in keyof T ] : T [ K ] } ;
@@ -76,6 +102,44 @@ function example(x: Union) {
76102 if (is(x)) { }
77103 x; // Union
78104}
105+
106+ function checksArrayOrObject1 ( obj : Record < string , any > | Record< string , any > []) {
107+ // "accidentally" guards the first branch on the length
108+ if ( Array . isArray ( obj ) && obj . length ) {
109+ for ( let key in obj ) {
110+ if ( obj [ key ] !== undefined ) {
111+ console . log ( obj [ key ] )
112+ }
113+ }
114+ }
115+ else {
116+ // 'obj' should probably not include an array type here.
117+ for ( let key in obj ) {
118+ if ( obj [ key ] !== undefined ) {
119+ console . log ( obj [ key ] )
120+ }
121+ }
122+ }
123+ }
124+
125+ function checksArrayOrObject2 ( obj : Record < string , any > | Record< string , any > []) {
126+ if ( Array . isArray ( obj ) ) {
127+ // obj should only be an array type here
128+ for ( let key in obj ) {
129+ if ( obj [ key ] !== undefined ) {
130+ console . log ( obj [ key ] )
131+ }
132+ }
133+ }
134+ else {
135+ // 'obj' should probably not include an array type here.
136+ for ( let key in obj ) {
137+ if ( obj [ key ] !== undefined ) {
138+ console . log ( obj [ key ] )
139+ }
140+ }
141+ }
142+ }
79143
80144
81145//// [narrowingMutualSubtypes.js]
@@ -92,7 +156,7 @@ var a3b = [r3, c3]; // {}[]
92156var c4 = { } ;
93157var a4a = [c4, r4]; // { } []
94158var a4b = [r4, c4]; // { } []
95- function gg ( x ) {
159+ function gg1 (x) {
96160 if ( isObject1 ( x ) ) {
97161 x ; // Record<string, unknown>
98162 }
@@ -103,13 +167,31 @@ function gg(x) {
103167}
104168function gg2 ( x ) {
105169 if ( isObject2 ( x ) ) {
106- x ; // {}
170+ x ; // Record<string, unknown>
107171 }
108172 else {
109- x ; // Record<string, unknown>
173+ x ; // never
110174 }
111175 x; // Record< string , unknown >
112176}
177+ function gg3 ( x ) {
178+ if ( isObject3 ( x ) ) {
179+ x ; // Record<string, any>
180+ }
181+ else {
182+ x ; // {}
183+ }
184+ x; // { }
185+ }
186+ function gg4 ( x ) {
187+ if ( isObject4 ( x ) ) {
188+ x ; // Record<string, any>
189+ }
190+ else {
191+ x ; // never
192+ }
193+ x; // Record< string , any >
194+ }
113195function is ( value ) {
114196 return true ;
115197}
@@ -124,3 +206,39 @@ function example(x) {
124206 if (is(x)) { }
125207 x; // Union
126208}
209+ function checksArrayOrObject1 ( obj ) {
210+ // "accidentally" guards the first branch on the length
211+ if ( Array . isArray ( obj ) && obj . length ) {
212+ for ( var key in obj ) {
213+ if ( obj [ key ] !== undefined ) {
214+ console . log ( obj [ key ] ) ;
215+ }
216+ }
217+ }
218+ else {
219+ // 'obj' should probably not include an array type here.
220+ for ( var key in obj ) {
221+ if ( obj [ key ] !== undefined ) {
222+ console . log ( obj [ key ] ) ;
223+ }
224+ }
225+ }
226+ }
227+ function checksArrayOrObject2 ( obj ) {
228+ if ( Array . isArray ( obj ) ) {
229+ // obj should only be an array type here
230+ for ( var key in obj ) {
231+ if ( obj [ key ] !== undefined ) {
232+ console . log ( obj [ key ] ) ;
233+ }
234+ }
235+ }
236+ else {
237+ // 'obj' should probably not include an array type here.
238+ for ( var key in obj ) {
239+ if ( obj [ key ] !== undefined ) {
240+ console . log ( obj [ key ] ) ;
241+ }
242+ }
243+ }
244+ }
0 commit comments