Skip to content

Commit 5374fd9

Browse files
authored
Add an additional test for favoring the asserted type in type predicate narrowing (#50065)
* Add an additional test for favoring the asserted type in type predicate narrowing * Add requested test cases
1 parent 4caa3f1 commit 5374fd9

4 files changed

+266
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
tests/cases/compiler/controlFlowFavorAssertedTypeThroughTypePredicate.ts(26,5): error TS7053: Element implicitly has an 'any' type because expression of type '"attr"' can't be used to index type '{}'.
2+
Property 'attr' does not exist on type '{}'.
3+
tests/cases/compiler/controlFlowFavorAssertedTypeThroughTypePredicate.ts(34,5): error TS7053: Element implicitly has an 'any' type because expression of type '"attr"' can't be used to index type '{}'.
4+
Property 'attr' does not exist on type '{}'.
5+
6+
7+
==== tests/cases/compiler/controlFlowFavorAssertedTypeThroughTypePredicate.ts (2 errors) ====
8+
// repro 49988#issuecomment-1192016929
9+
10+
declare function isObject1(value: unknown): value is Record<string, unknown>;
11+
12+
declare const obj1: {};
13+
if (isObject1(obj1)) {
14+
obj1;
15+
obj1['attr'];
16+
}
17+
// check type after conditional block
18+
obj1;
19+
20+
declare const obj2: {} | undefined;
21+
if (isObject1(obj2)) {
22+
obj2;
23+
obj2['attr'];
24+
}
25+
// check type after conditional block
26+
obj2;
27+
28+
declare function isObject2(value: unknown): value is {};
29+
30+
declare const obj3: Record<string, unknown>;
31+
if (isObject2(obj3)) {
32+
obj3;
33+
obj3['attr'];
34+
~~~~~~~~~~~~
35+
!!! error TS7053: Element implicitly has an 'any' type because expression of type '"attr"' can't be used to index type '{}'.
36+
!!! error TS7053: Property 'attr' does not exist on type '{}'.
37+
}
38+
// check type after conditional block
39+
obj3;
40+
41+
declare const obj4: Record<string, unknown> | undefined;
42+
if (isObject2(obj4)) {
43+
obj4;
44+
obj4['attr'];
45+
~~~~~~~~~~~~
46+
!!! error TS7053: Element implicitly has an 'any' type because expression of type '"attr"' can't be used to index type '{}'.
47+
!!! error TS7053: Property 'attr' does not exist on type '{}'.
48+
}
49+
// check type after conditional block
50+
obj4;
51+
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
=== tests/cases/compiler/controlFlowFavorAssertedTypeThroughTypePredicate.ts ===
2+
// repro 49988#issuecomment-1192016929
3+
4+
declare function isObject1(value: unknown): value is Record<string, unknown>;
5+
>isObject1 : Symbol(isObject1, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 0, 0))
6+
>value : Symbol(value, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 2, 27))
7+
>value : Symbol(value, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 2, 27))
8+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
9+
10+
declare const obj1: {};
11+
>obj1 : Symbol(obj1, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 4, 13))
12+
13+
if (isObject1(obj1)) {
14+
>isObject1 : Symbol(isObject1, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 0, 0))
15+
>obj1 : Symbol(obj1, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 4, 13))
16+
17+
obj1;
18+
>obj1 : Symbol(obj1, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 4, 13))
19+
20+
obj1['attr'];
21+
>obj1 : Symbol(obj1, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 4, 13))
22+
}
23+
// check type after conditional block
24+
obj1;
25+
>obj1 : Symbol(obj1, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 4, 13))
26+
27+
declare const obj2: {} | undefined;
28+
>obj2 : Symbol(obj2, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 12, 13))
29+
30+
if (isObject1(obj2)) {
31+
>isObject1 : Symbol(isObject1, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 0, 0))
32+
>obj2 : Symbol(obj2, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 12, 13))
33+
34+
obj2;
35+
>obj2 : Symbol(obj2, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 12, 13))
36+
37+
obj2['attr'];
38+
>obj2 : Symbol(obj2, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 12, 13))
39+
}
40+
// check type after conditional block
41+
obj2;
42+
>obj2 : Symbol(obj2, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 12, 13))
43+
44+
declare function isObject2(value: unknown): value is {};
45+
>isObject2 : Symbol(isObject2, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 18, 5))
46+
>value : Symbol(value, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 20, 27))
47+
>value : Symbol(value, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 20, 27))
48+
49+
declare const obj3: Record<string, unknown>;
50+
>obj3 : Symbol(obj3, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 22, 13))
51+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
52+
53+
if (isObject2(obj3)) {
54+
>isObject2 : Symbol(isObject2, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 18, 5))
55+
>obj3 : Symbol(obj3, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 22, 13))
56+
57+
obj3;
58+
>obj3 : Symbol(obj3, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 22, 13))
59+
60+
obj3['attr'];
61+
>obj3 : Symbol(obj3, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 22, 13))
62+
}
63+
// check type after conditional block
64+
obj3;
65+
>obj3 : Symbol(obj3, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 22, 13))
66+
67+
declare const obj4: Record<string, unknown> | undefined;
68+
>obj4 : Symbol(obj4, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 30, 13))
69+
>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --))
70+
71+
if (isObject2(obj4)) {
72+
>isObject2 : Symbol(isObject2, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 18, 5))
73+
>obj4 : Symbol(obj4, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 30, 13))
74+
75+
obj4;
76+
>obj4 : Symbol(obj4, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 30, 13))
77+
78+
obj4['attr'];
79+
>obj4 : Symbol(obj4, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 30, 13))
80+
}
81+
// check type after conditional block
82+
obj4;
83+
>obj4 : Symbol(obj4, Decl(controlFlowFavorAssertedTypeThroughTypePredicate.ts, 30, 13))
84+
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
=== tests/cases/compiler/controlFlowFavorAssertedTypeThroughTypePredicate.ts ===
2+
// repro 49988#issuecomment-1192016929
3+
4+
declare function isObject1(value: unknown): value is Record<string, unknown>;
5+
>isObject1 : (value: unknown) => value is Record<string, unknown>
6+
>value : unknown
7+
8+
declare const obj1: {};
9+
>obj1 : {}
10+
11+
if (isObject1(obj1)) {
12+
>isObject1(obj1) : boolean
13+
>isObject1 : (value: unknown) => value is Record<string, unknown>
14+
>obj1 : {}
15+
16+
obj1;
17+
>obj1 : Record<string, unknown>
18+
19+
obj1['attr'];
20+
>obj1['attr'] : unknown
21+
>obj1 : Record<string, unknown>
22+
>'attr' : "attr"
23+
}
24+
// check type after conditional block
25+
obj1;
26+
>obj1 : Record<string, unknown>
27+
28+
declare const obj2: {} | undefined;
29+
>obj2 : {} | undefined
30+
31+
if (isObject1(obj2)) {
32+
>isObject1(obj2) : boolean
33+
>isObject1 : (value: unknown) => value is Record<string, unknown>
34+
>obj2 : {} | undefined
35+
36+
obj2;
37+
>obj2 : Record<string, unknown>
38+
39+
obj2['attr'];
40+
>obj2['attr'] : unknown
41+
>obj2 : Record<string, unknown>
42+
>'attr' : "attr"
43+
}
44+
// check type after conditional block
45+
obj2;
46+
>obj2 : Record<string, unknown> | undefined
47+
48+
declare function isObject2(value: unknown): value is {};
49+
>isObject2 : (value: unknown) => value is {}
50+
>value : unknown
51+
52+
declare const obj3: Record<string, unknown>;
53+
>obj3 : Record<string, unknown>
54+
55+
if (isObject2(obj3)) {
56+
>isObject2(obj3) : boolean
57+
>isObject2 : (value: unknown) => value is {}
58+
>obj3 : Record<string, unknown>
59+
60+
obj3;
61+
>obj3 : {}
62+
63+
obj3['attr'];
64+
>obj3['attr'] : any
65+
>obj3 : {}
66+
>'attr' : "attr"
67+
}
68+
// check type after conditional block
69+
obj3;
70+
>obj3 : {}
71+
72+
declare const obj4: Record<string, unknown> | undefined;
73+
>obj4 : Record<string, unknown> | undefined
74+
75+
if (isObject2(obj4)) {
76+
>isObject2(obj4) : boolean
77+
>isObject2 : (value: unknown) => value is {}
78+
>obj4 : Record<string, unknown> | undefined
79+
80+
obj4;
81+
>obj4 : {}
82+
83+
obj4['attr'];
84+
>obj4['attr'] : any
85+
>obj4 : {}
86+
>'attr' : "attr"
87+
}
88+
// check type after conditional block
89+
obj4;
90+
>obj4 : {} | undefined
91+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// @noEmit: true
2+
// @strict: true
3+
4+
// repro 49988#issuecomment-1192016929
5+
6+
declare function isObject1(value: unknown): value is Record<string, unknown>;
7+
8+
declare const obj1: {};
9+
if (isObject1(obj1)) {
10+
obj1;
11+
obj1['attr'];
12+
}
13+
// check type after conditional block
14+
obj1;
15+
16+
declare const obj2: {} | undefined;
17+
if (isObject1(obj2)) {
18+
obj2;
19+
obj2['attr'];
20+
}
21+
// check type after conditional block
22+
obj2;
23+
24+
declare function isObject2(value: unknown): value is {};
25+
26+
declare const obj3: Record<string, unknown>;
27+
if (isObject2(obj3)) {
28+
obj3;
29+
obj3['attr'];
30+
}
31+
// check type after conditional block
32+
obj3;
33+
34+
declare const obj4: Record<string, unknown> | undefined;
35+
if (isObject2(obj4)) {
36+
obj4;
37+
obj4['attr'];
38+
}
39+
// check type after conditional block
40+
obj4;

0 commit comments

Comments
 (0)