Skip to content

Commit d2f324b

Browse files
authored
Add test for intersection narrowing bug (#45296)
1 parent 9cc3070 commit d2f324b

File tree

4 files changed

+190
-0
lines changed

4 files changed

+190
-0
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//// [narrowingIntersection.ts]
2+
// Somehow this being an intersection matters.
3+
type FooAndBaz = { foo: unknown } & { baz: unknown };
4+
5+
type Disjoint =
6+
| { readonly value: string; readonly err?: never; }
7+
| { readonly value?: never; readonly err: FooAndBaz; };
8+
9+
function test1(result: Disjoint): string {
10+
if (result.err) {
11+
throw result.err;
12+
}
13+
// Error, should OK
14+
return result.value;
15+
}
16+
17+
type TrivialIntersection = { a: 1 } & { a: 1 };
18+
19+
function want0(x: 0) {}
20+
21+
function test2(a: 0 | TrivialIntersection) {
22+
if (a === 0) {
23+
want0(a); // Fails, but expect to work
24+
}
25+
}
26+
27+
//// [narrowingIntersection.js]
28+
function test1(result) {
29+
if (result.err) {
30+
throw result.err;
31+
}
32+
// Error, should OK
33+
return result.value;
34+
}
35+
function want0(x) { }
36+
function test2(a) {
37+
if (a === 0) {
38+
want0(a); // Fails, but expect to work
39+
}
40+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
=== tests/cases/compiler/narrowingIntersection.ts ===
2+
// Somehow this being an intersection matters.
3+
type FooAndBaz = { foo: unknown } & { baz: unknown };
4+
>FooAndBaz : Symbol(FooAndBaz, Decl(narrowingIntersection.ts, 0, 0))
5+
>foo : Symbol(foo, Decl(narrowingIntersection.ts, 1, 18))
6+
>baz : Symbol(baz, Decl(narrowingIntersection.ts, 1, 37))
7+
8+
type Disjoint =
9+
>Disjoint : Symbol(Disjoint, Decl(narrowingIntersection.ts, 1, 53))
10+
11+
| { readonly value: string; readonly err?: never; }
12+
>value : Symbol(value, Decl(narrowingIntersection.ts, 4, 4))
13+
>err : Symbol(err, Decl(narrowingIntersection.ts, 4, 28))
14+
15+
| { readonly value?: never; readonly err: FooAndBaz; };
16+
>value : Symbol(value, Decl(narrowingIntersection.ts, 5, 4))
17+
>err : Symbol(err, Decl(narrowingIntersection.ts, 5, 28))
18+
>FooAndBaz : Symbol(FooAndBaz, Decl(narrowingIntersection.ts, 0, 0))
19+
20+
function test1(result: Disjoint): string {
21+
>test1 : Symbol(test1, Decl(narrowingIntersection.ts, 5, 56))
22+
>result : Symbol(result, Decl(narrowingIntersection.ts, 7, 15))
23+
>Disjoint : Symbol(Disjoint, Decl(narrowingIntersection.ts, 1, 53))
24+
25+
if (result.err) {
26+
>result.err : Symbol(err, Decl(narrowingIntersection.ts, 4, 28), Decl(narrowingIntersection.ts, 5, 28))
27+
>result : Symbol(result, Decl(narrowingIntersection.ts, 7, 15))
28+
>err : Symbol(err, Decl(narrowingIntersection.ts, 4, 28), Decl(narrowingIntersection.ts, 5, 28))
29+
30+
throw result.err;
31+
>result.err : Symbol(err, Decl(narrowingIntersection.ts, 4, 28), Decl(narrowingIntersection.ts, 5, 28))
32+
>result : Symbol(result, Decl(narrowingIntersection.ts, 7, 15))
33+
>err : Symbol(err, Decl(narrowingIntersection.ts, 4, 28), Decl(narrowingIntersection.ts, 5, 28))
34+
}
35+
// Error, should OK
36+
return result.value;
37+
>result.value : Symbol(value, Decl(narrowingIntersection.ts, 4, 4), Decl(narrowingIntersection.ts, 5, 4))
38+
>result : Symbol(result, Decl(narrowingIntersection.ts, 7, 15))
39+
>value : Symbol(value, Decl(narrowingIntersection.ts, 4, 4), Decl(narrowingIntersection.ts, 5, 4))
40+
}
41+
42+
type TrivialIntersection = { a: 1 } & { a: 1 };
43+
>TrivialIntersection : Symbol(TrivialIntersection, Decl(narrowingIntersection.ts, 13, 1))
44+
>a : Symbol(a, Decl(narrowingIntersection.ts, 15, 28))
45+
>a : Symbol(a, Decl(narrowingIntersection.ts, 15, 39))
46+
47+
function want0(x: 0) {}
48+
>want0 : Symbol(want0, Decl(narrowingIntersection.ts, 15, 47))
49+
>x : Symbol(x, Decl(narrowingIntersection.ts, 17, 15))
50+
51+
function test2(a: 0 | TrivialIntersection) {
52+
>test2 : Symbol(test2, Decl(narrowingIntersection.ts, 17, 23))
53+
>a : Symbol(a, Decl(narrowingIntersection.ts, 19, 15))
54+
>TrivialIntersection : Symbol(TrivialIntersection, Decl(narrowingIntersection.ts, 13, 1))
55+
56+
if (a === 0) {
57+
>a : Symbol(a, Decl(narrowingIntersection.ts, 19, 15))
58+
59+
want0(a); // Fails, but expect to work
60+
>want0 : Symbol(want0, Decl(narrowingIntersection.ts, 15, 47))
61+
>a : Symbol(a, Decl(narrowingIntersection.ts, 19, 15))
62+
}
63+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
=== tests/cases/compiler/narrowingIntersection.ts ===
2+
// Somehow this being an intersection matters.
3+
type FooAndBaz = { foo: unknown } & { baz: unknown };
4+
>FooAndBaz : FooAndBaz
5+
>foo : unknown
6+
>baz : unknown
7+
8+
type Disjoint =
9+
>Disjoint : Disjoint
10+
11+
| { readonly value: string; readonly err?: never; }
12+
>value : string
13+
>err : never
14+
15+
| { readonly value?: never; readonly err: FooAndBaz; };
16+
>value : never
17+
>err : FooAndBaz
18+
19+
function test1(result: Disjoint): string {
20+
>test1 : (result: Disjoint) => string
21+
>result : Disjoint
22+
23+
if (result.err) {
24+
>result.err : FooAndBaz
25+
>result : Disjoint
26+
>err : FooAndBaz
27+
28+
throw result.err;
29+
>result.err : FooAndBaz
30+
>result : Disjoint
31+
>err : FooAndBaz
32+
}
33+
// Error, should OK
34+
return result.value;
35+
>result.value : string
36+
>result : Disjoint
37+
>value : string
38+
}
39+
40+
type TrivialIntersection = { a: 1 } & { a: 1 };
41+
>TrivialIntersection : TrivialIntersection
42+
>a : 1
43+
>a : 1
44+
45+
function want0(x: 0) {}
46+
>want0 : (x: 0) => void
47+
>x : 0
48+
49+
function test2(a: 0 | TrivialIntersection) {
50+
>test2 : (a: 0 | TrivialIntersection) => void
51+
>a : 0 | TrivialIntersection
52+
53+
if (a === 0) {
54+
>a === 0 : boolean
55+
>a : 0 | TrivialIntersection
56+
>0 : 0
57+
58+
want0(a); // Fails, but expect to work
59+
>want0(a) : void
60+
>want0 : (x: 0) => void
61+
>a : 0
62+
}
63+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Somehow this being an intersection matters.
2+
type FooAndBaz = { foo: unknown } & { baz: unknown };
3+
4+
type Disjoint =
5+
| { readonly value: string; readonly err?: never; }
6+
| { readonly value?: never; readonly err: FooAndBaz; };
7+
8+
function test1(result: Disjoint): string {
9+
if (result.err) {
10+
throw result.err;
11+
}
12+
// Error, should OK
13+
return result.value;
14+
}
15+
16+
type TrivialIntersection = { a: 1 } & { a: 1 };
17+
18+
function want0(x: 0) {}
19+
20+
function test2(a: 0 | TrivialIntersection) {
21+
if (a === 0) {
22+
want0(a); // Fails, but expect to work
23+
}
24+
}

0 commit comments

Comments
 (0)