Skip to content

Commit 713c0e0

Browse files
Merge pull request #7203 from Microsoft/intersectionErrors
Stop elaborating errors when relating intersection constituents
2 parents 9b7d72c + 818c76c commit 713c0e0

15 files changed

+359
-38
lines changed

src/compiler/checker.ts

+14-2
Original file line numberDiff line numberDiff line change
@@ -5521,8 +5521,20 @@ namespace ts {
55215521
// on either side that need to be prioritized. For example, A | B = (A | B) & (C | D) or
55225522
// A & B = (A & B) | (C & D).
55235523
if (source.flags & TypeFlags.Intersection) {
5524-
// If target is a union type the following check will report errors so we suppress them here
5525-
if (result = someTypeRelatedToType(<IntersectionType>source, target, reportErrors && !(target.flags & TypeFlags.Union))) {
5524+
// Check to see if any constituents of the intersection are immediately related to the target.
5525+
//
5526+
// Don't report errors though. Checking whether a constituent is related to the source is not actually
5527+
// useful and leads to some confusing error messages. Instead it is better to let the below checks
5528+
// take care of this, or to not elaborate at all. For instance,
5529+
//
5530+
// - For an object type (such as 'C = A & B'), users are usually more interested in structural errors.
5531+
//
5532+
// - For a union type (such as '(A | B) = (C & D)'), it's better to hold onto the whole intersection
5533+
// than to report that 'D' is not assignable to 'A' or 'B'.
5534+
//
5535+
// - For a primitive type or type parameter (such as 'number = A & B') there is no point in
5536+
// breaking the intersection apart.
5537+
if (result = someTypeRelatedToType(<IntersectionType>source, target, /*reportErrors*/ false)) {
55265538
return result;
55275539
}
55285540
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
tests/cases/compiler/errorMessagesIntersectionTypes01.ts(14,5): error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'.
2+
Types of property 'fooProp' are incompatible.
3+
Type 'string' is not assignable to type 'boolean'.
4+
5+
6+
==== tests/cases/compiler/errorMessagesIntersectionTypes01.ts (1 errors) ====
7+
interface Foo {
8+
fooProp: boolean;
9+
}
10+
11+
interface Bar {
12+
barProp: string;
13+
}
14+
15+
interface FooBar extends Foo, Bar {
16+
}
17+
18+
declare function mixBar<T>(obj: T): T & Bar;
19+
20+
let fooBar: FooBar = mixBar({
21+
~~~~~~
22+
!!! error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'.
23+
!!! error TS2322: Types of property 'fooProp' are incompatible.
24+
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
25+
fooProp: "frizzlebizzle"
26+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//// [errorMessagesIntersectionTypes01.ts]
2+
interface Foo {
3+
fooProp: boolean;
4+
}
5+
6+
interface Bar {
7+
barProp: string;
8+
}
9+
10+
interface FooBar extends Foo, Bar {
11+
}
12+
13+
declare function mixBar<T>(obj: T): T & Bar;
14+
15+
let fooBar: FooBar = mixBar({
16+
fooProp: "frizzlebizzle"
17+
});
18+
19+
//// [errorMessagesIntersectionTypes01.js]
20+
var fooBar = mixBar({
21+
fooProp: "frizzlebizzle"
22+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
tests/cases/compiler/errorMessagesIntersectionTypes02.ts(14,5): error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'.
2+
Types of property 'fooProp' are incompatible.
3+
Type 'string' is not assignable to type '"hello" | "world"'.
4+
Type 'string' is not assignable to type '"world"'.
5+
6+
7+
==== tests/cases/compiler/errorMessagesIntersectionTypes02.ts (1 errors) ====
8+
interface Foo {
9+
fooProp: "hello" | "world";
10+
}
11+
12+
interface Bar {
13+
barProp: string;
14+
}
15+
16+
interface FooBar extends Foo, Bar {
17+
}
18+
19+
declare function mixBar<T>(obj: T): T & Bar;
20+
21+
let fooBar: FooBar = mixBar({
22+
~~~~~~
23+
!!! error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'.
24+
!!! error TS2322: Types of property 'fooProp' are incompatible.
25+
!!! error TS2322: Type 'string' is not assignable to type '"hello" | "world"'.
26+
!!! error TS2322: Type 'string' is not assignable to type '"world"'.
27+
fooProp: "frizzlebizzle"
28+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//// [errorMessagesIntersectionTypes02.ts]
2+
interface Foo {
3+
fooProp: "hello" | "world";
4+
}
5+
6+
interface Bar {
7+
barProp: string;
8+
}
9+
10+
interface FooBar extends Foo, Bar {
11+
}
12+
13+
declare function mixBar<T>(obj: T): T & Bar;
14+
15+
let fooBar: FooBar = mixBar({
16+
fooProp: "frizzlebizzle"
17+
});
18+
19+
//// [errorMessagesIntersectionTypes02.js]
20+
var fooBar = mixBar({
21+
fooProp: "frizzlebizzle"
22+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
tests/cases/compiler/errorMessagesIntersectionTypes03.ts(17,5): error TS2322: Type 'A & B' is not assignable to type 'T'.
2+
tests/cases/compiler/errorMessagesIntersectionTypes03.ts(18,5): error TS2322: Type 'A & B' is not assignable to type 'U'.
3+
tests/cases/compiler/errorMessagesIntersectionTypes03.ts(19,5): error TS2322: Type 'A & B' is not assignable to type 'V'.
4+
tests/cases/compiler/errorMessagesIntersectionTypes03.ts(22,5): error TS2322: Type 'T & B' is not assignable to type 'U'.
5+
tests/cases/compiler/errorMessagesIntersectionTypes03.ts(23,5): error TS2322: Type 'T & B' is not assignable to type 'V'.
6+
7+
8+
==== tests/cases/compiler/errorMessagesIntersectionTypes03.ts (5 errors) ====
9+
interface A {
10+
a;
11+
}
12+
13+
interface B {
14+
b;
15+
}
16+
17+
function f<T, U extends A, V extends U>(): void {
18+
let t: T;
19+
let u: U;
20+
let v: V;
21+
22+
let a_and_b: A & B;
23+
let t_and_b: T & B;
24+
25+
t = a_and_b;
26+
~
27+
!!! error TS2322: Type 'A & B' is not assignable to type 'T'.
28+
u = a_and_b;
29+
~
30+
!!! error TS2322: Type 'A & B' is not assignable to type 'U'.
31+
v = a_and_b;
32+
~
33+
!!! error TS2322: Type 'A & B' is not assignable to type 'V'.
34+
35+
t = t_and_b;
36+
u = t_and_b;
37+
~
38+
!!! error TS2322: Type 'T & B' is not assignable to type 'U'.
39+
v = t_and_b;
40+
~
41+
!!! error TS2322: Type 'T & B' is not assignable to type 'V'.
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//// [errorMessagesIntersectionTypes03.ts]
2+
interface A {
3+
a;
4+
}
5+
6+
interface B {
7+
b;
8+
}
9+
10+
function f<T, U extends A, V extends U>(): void {
11+
let t: T;
12+
let u: U;
13+
let v: V;
14+
15+
let a_and_b: A & B;
16+
let t_and_b: T & B;
17+
18+
t = a_and_b;
19+
u = a_and_b;
20+
v = a_and_b;
21+
22+
t = t_and_b;
23+
u = t_and_b;
24+
v = t_and_b;
25+
}
26+
27+
//// [errorMessagesIntersectionTypes03.js]
28+
function f() {
29+
var t;
30+
var u;
31+
var v;
32+
var a_and_b;
33+
var t_and_b;
34+
t = a_and_b;
35+
u = a_and_b;
36+
v = a_and_b;
37+
t = t_and_b;
38+
u = t_and_b;
39+
v = t_and_b;
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
tests/cases/compiler/errorMessagesIntersectionTypes04.ts(17,5): error TS2322: Type 'A & B' is not assignable to type 'number'.
2+
tests/cases/compiler/errorMessagesIntersectionTypes04.ts(18,5): error TS2322: Type 'A & B' is not assignable to type 'boolean'.
3+
tests/cases/compiler/errorMessagesIntersectionTypes04.ts(19,5): error TS2322: Type 'A & B' is not assignable to type 'string'.
4+
tests/cases/compiler/errorMessagesIntersectionTypes04.ts(21,5): error TS2322: Type 'number & boolean' is not assignable to type 'string'.
5+
6+
7+
==== tests/cases/compiler/errorMessagesIntersectionTypes04.ts (4 errors) ====
8+
interface A {
9+
a;
10+
}
11+
12+
interface B {
13+
b;
14+
}
15+
16+
function f<T, U extends A, V extends U>(): void {
17+
let num: number;
18+
let bool: boolean;
19+
let str: string;
20+
21+
let a_and_b: A & B;
22+
let num_and_bool: number & boolean;
23+
24+
num = a_and_b;
25+
~~~
26+
!!! error TS2322: Type 'A & B' is not assignable to type 'number'.
27+
bool = a_and_b;
28+
~~~~
29+
!!! error TS2322: Type 'A & B' is not assignable to type 'boolean'.
30+
str = a_and_b;
31+
~~~
32+
!!! error TS2322: Type 'A & B' is not assignable to type 'string'.
33+
34+
str = num_and_bool;
35+
~~~
36+
!!! error TS2322: Type 'number & boolean' is not assignable to type 'string'.
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//// [errorMessagesIntersectionTypes04.ts]
2+
interface A {
3+
a;
4+
}
5+
6+
interface B {
7+
b;
8+
}
9+
10+
function f<T, U extends A, V extends U>(): void {
11+
let num: number;
12+
let bool: boolean;
13+
let str: string;
14+
15+
let a_and_b: A & B;
16+
let num_and_bool: number & boolean;
17+
18+
num = a_and_b;
19+
bool = a_and_b;
20+
str = a_and_b;
21+
22+
str = num_and_bool;
23+
}
24+
25+
//// [errorMessagesIntersectionTypes04.js]
26+
function f() {
27+
var num;
28+
var bool;
29+
var str;
30+
var a_and_b;
31+
var num_and_bool;
32+
num = a_and_b;
33+
bool = a_and_b;
34+
str = a_and_b;
35+
str = num_and_bool;
36+
}

0 commit comments

Comments
 (0)