Skip to content

Commit 72068e2

Browse files
Merge pull request microsoft#25115 from Microsoft/matchingTypeRefs
Improved errors using type reference targets
2 parents 51e7ae0 + 6d755aa commit 72068e2

7 files changed

+543
-6
lines changed

src/compiler/checker.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10823,12 +10823,32 @@ namespace ts {
1082310823
}
1082410824
}
1082510825
if (reportErrors) {
10826-
const discriminantType = findMatchingDiscriminantType(source, target);
10827-
isRelatedTo(source, discriminantType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true);
10826+
const bestMatchingType =
10827+
findMatchingDiscriminantType(source, target) ||
10828+
findMatchingTypeReferenceOrTypeAliasReference(source, target);
10829+
10830+
isRelatedTo(source, bestMatchingType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true);
1082810831
}
1082910832
return Ternary.False;
1083010833
}
1083110834

10835+
function findMatchingTypeReferenceOrTypeAliasReference(source: Type, unionTarget: UnionOrIntersectionType) {
10836+
if (source.flags & TypeFlags.Object && (source as ObjectType).objectFlags & (ObjectFlags.Reference | ObjectFlags.Anonymous) && unionTarget.flags & TypeFlags.Union) {
10837+
return find(unionTarget.types, target => {
10838+
if (target.flags & TypeFlags.Object) {
10839+
if ((source as ObjectType).objectFlags & (target as ObjectType).objectFlags & ObjectFlags.Reference) {
10840+
return (source as TypeReference).target === (target as TypeReference).target;
10841+
}
10842+
if ((source as ObjectType).objectFlags & (target as ObjectType).objectFlags & ObjectFlags.Anonymous) {
10843+
return !!(source as AnonymousType).aliasSymbol && (source as AnonymousType).aliasSymbol === (target as AnonymousType).aliasSymbol;
10844+
}
10845+
}
10846+
return false;
10847+
});
10848+
}
10849+
}
10850+
10851+
1083210852
// Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly
1083310853
function findMatchingDiscriminantType(source: Type, target: UnionOrIntersectionType) {
1083410854
let match: Type | undefined;

tests/baselines/reference/for-of39.errors.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ tests/cases/conformance/es6/for-ofStatements/for-of39.ts(1,19): error TS2345: Ar
44
Types of parameters 'items' and 'items' are incompatible.
55
Type 'ConcatArray<[string, boolean]>' is not assignable to type 'ConcatArray<[string, number] | [string, true]>'.
66
Type '[string, boolean]' is not assignable to type '[string, number] | [string, true]'.
7-
Type '[string, boolean]' is not assignable to type '[string, true]'.
8-
Type 'boolean' is not assignable to type 'true'.
7+
Type '[string, boolean]' is not assignable to type '[string, number]'.
8+
Type 'boolean' is not assignable to type 'number'.
99

1010

1111
==== tests/cases/conformance/es6/for-ofStatements/for-of39.ts (1 errors) ====
@@ -17,8 +17,8 @@ tests/cases/conformance/es6/for-ofStatements/for-of39.ts(1,19): error TS2345: Ar
1717
!!! error TS2345: Types of parameters 'items' and 'items' are incompatible.
1818
!!! error TS2345: Type 'ConcatArray<[string, boolean]>' is not assignable to type 'ConcatArray<[string, number] | [string, true]>'.
1919
!!! error TS2345: Type '[string, boolean]' is not assignable to type '[string, number] | [string, true]'.
20-
!!! error TS2345: Type '[string, boolean]' is not assignable to type '[string, true]'.
21-
!!! error TS2345: Type 'boolean' is not assignable to type 'true'.
20+
!!! error TS2345: Type '[string, boolean]' is not assignable to type '[string, number]'.
21+
!!! error TS2345: Type 'boolean' is not assignable to type 'number'.
2222
for (var [k, v] of map) {
2323
k;
2424
v;
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
tests/cases/compiler/unionTypeErrorMessageTypeRefs01.ts(25,1): error TS2322: Type 'A<Foo>' is not assignable to type 'A<Bar> | B<Baz> | C<Kwah>'.
2+
Type 'A<Foo>' is not assignable to type 'A<Bar>'.
3+
Type 'Foo' is not assignable to type 'Bar'.
4+
Property 'bar' is missing in type 'Foo'.
5+
tests/cases/compiler/unionTypeErrorMessageTypeRefs01.ts(26,1): error TS2322: Type 'B<Foo>' is not assignable to type 'A<Bar> | B<Baz> | C<Kwah>'.
6+
Type 'B<Foo>' is not assignable to type 'B<Baz>'.
7+
Type 'Foo' is not assignable to type 'Baz'.
8+
Property 'baz' is missing in type 'Foo'.
9+
tests/cases/compiler/unionTypeErrorMessageTypeRefs01.ts(27,1): error TS2322: Type 'C<Foo>' is not assignable to type 'A<Bar> | B<Baz> | C<Kwah>'.
10+
Type 'C<Foo>' is not assignable to type 'C<Kwah>'.
11+
Type 'Foo' is not assignable to type 'Kwah'.
12+
Property 'kwah' is missing in type 'Foo'.
13+
tests/cases/compiler/unionTypeErrorMessageTypeRefs01.ts(48,1): error TS2322: Type 'X<Foo>' is not assignable to type 'X<Bar> | Y<Baz> | Z<Kwah>'.
14+
Type 'X<Foo>' is not assignable to type 'X<Bar>'.
15+
Types of property 'xProp' are incompatible.
16+
Type 'Foo' is not assignable to type 'Bar'.
17+
tests/cases/compiler/unionTypeErrorMessageTypeRefs01.ts(49,1): error TS2322: Type 'Y<Foo>' is not assignable to type 'X<Bar> | Y<Baz> | Z<Kwah>'.
18+
Type 'Y<Foo>' is not assignable to type 'Y<Baz>'.
19+
Types of property 'yProp' are incompatible.
20+
Type 'Foo' is not assignable to type 'Baz'.
21+
tests/cases/compiler/unionTypeErrorMessageTypeRefs01.ts(50,1): error TS2322: Type 'Z<Foo>' is not assignable to type 'X<Bar> | Y<Baz> | Z<Kwah>'.
22+
Type 'Z<Foo>' is not assignable to type 'Z<Kwah>'.
23+
Types of property 'zProp' are incompatible.
24+
Type 'Foo' is not assignable to type 'Kwah'.
25+
26+
27+
==== tests/cases/compiler/unionTypeErrorMessageTypeRefs01.ts (6 errors) ====
28+
interface Foo { foo: any }
29+
interface Bar { bar: any }
30+
interface Baz { baz: any }
31+
interface Kwah { kwah: any }
32+
33+
////////
34+
35+
interface A<T> {
36+
aProp: T;
37+
}
38+
39+
interface B<T> {
40+
bProp: T;
41+
}
42+
43+
interface C<T> {
44+
cProp: T;
45+
}
46+
47+
declare const a: A<Foo>;
48+
declare const b: B<Foo>;
49+
declare const c: C<Foo>;
50+
declare let thingOfInterfaces: A<Bar> | B<Baz> | C<Kwah>;
51+
52+
thingOfInterfaces = a;
53+
~~~~~~~~~~~~~~~~~
54+
!!! error TS2322: Type 'A<Foo>' is not assignable to type 'A<Bar> | B<Baz> | C<Kwah>'.
55+
!!! error TS2322: Type 'A<Foo>' is not assignable to type 'A<Bar>'.
56+
!!! error TS2322: Type 'Foo' is not assignable to type 'Bar'.
57+
!!! error TS2322: Property 'bar' is missing in type 'Foo'.
58+
thingOfInterfaces = b;
59+
~~~~~~~~~~~~~~~~~
60+
!!! error TS2322: Type 'B<Foo>' is not assignable to type 'A<Bar> | B<Baz> | C<Kwah>'.
61+
!!! error TS2322: Type 'B<Foo>' is not assignable to type 'B<Baz>'.
62+
!!! error TS2322: Type 'Foo' is not assignable to type 'Baz'.
63+
!!! error TS2322: Property 'baz' is missing in type 'Foo'.
64+
thingOfInterfaces = c;
65+
~~~~~~~~~~~~~~~~~
66+
!!! error TS2322: Type 'C<Foo>' is not assignable to type 'A<Bar> | B<Baz> | C<Kwah>'.
67+
!!! error TS2322: Type 'C<Foo>' is not assignable to type 'C<Kwah>'.
68+
!!! error TS2322: Type 'Foo' is not assignable to type 'Kwah'.
69+
!!! error TS2322: Property 'kwah' is missing in type 'Foo'.
70+
71+
////////
72+
73+
type X<T> = {
74+
xProp: T;
75+
}
76+
77+
type Y<T> = {
78+
yProp: T;
79+
}
80+
81+
type Z<T> = {
82+
zProp: T;
83+
}
84+
85+
declare const x: X<Foo>;
86+
declare const y: Y<Foo>;
87+
declare const z: Z<Foo>;
88+
declare let thingOfTypeAliases: X<Bar> | Y<Baz> | Z<Kwah>;
89+
90+
thingOfTypeAliases = x;
91+
~~~~~~~~~~~~~~~~~~
92+
!!! error TS2322: Type 'X<Foo>' is not assignable to type 'X<Bar> | Y<Baz> | Z<Kwah>'.
93+
!!! error TS2322: Type 'X<Foo>' is not assignable to type 'X<Bar>'.
94+
!!! error TS2322: Types of property 'xProp' are incompatible.
95+
!!! error TS2322: Type 'Foo' is not assignable to type 'Bar'.
96+
thingOfTypeAliases = y;
97+
~~~~~~~~~~~~~~~~~~
98+
!!! error TS2322: Type 'Y<Foo>' is not assignable to type 'X<Bar> | Y<Baz> | Z<Kwah>'.
99+
!!! error TS2322: Type 'Y<Foo>' is not assignable to type 'Y<Baz>'.
100+
!!! error TS2322: Types of property 'yProp' are incompatible.
101+
!!! error TS2322: Type 'Foo' is not assignable to type 'Baz'.
102+
thingOfTypeAliases = z;
103+
~~~~~~~~~~~~~~~~~~
104+
!!! error TS2322: Type 'Z<Foo>' is not assignable to type 'X<Bar> | Y<Baz> | Z<Kwah>'.
105+
!!! error TS2322: Type 'Z<Foo>' is not assignable to type 'Z<Kwah>'.
106+
!!! error TS2322: Types of property 'zProp' are incompatible.
107+
!!! error TS2322: Type 'Foo' is not assignable to type 'Kwah'.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
//// [unionTypeErrorMessageTypeRefs01.ts]
2+
interface Foo { foo: any }
3+
interface Bar { bar: any }
4+
interface Baz { baz: any }
5+
interface Kwah { kwah: any }
6+
7+
////////
8+
9+
interface A<T> {
10+
aProp: T;
11+
}
12+
13+
interface B<T> {
14+
bProp: T;
15+
}
16+
17+
interface C<T> {
18+
cProp: T;
19+
}
20+
21+
declare const a: A<Foo>;
22+
declare const b: B<Foo>;
23+
declare const c: C<Foo>;
24+
declare let thingOfInterfaces: A<Bar> | B<Baz> | C<Kwah>;
25+
26+
thingOfInterfaces = a;
27+
thingOfInterfaces = b;
28+
thingOfInterfaces = c;
29+
30+
////////
31+
32+
type X<T> = {
33+
xProp: T;
34+
}
35+
36+
type Y<T> = {
37+
yProp: T;
38+
}
39+
40+
type Z<T> = {
41+
zProp: T;
42+
}
43+
44+
declare const x: X<Foo>;
45+
declare const y: Y<Foo>;
46+
declare const z: Z<Foo>;
47+
declare let thingOfTypeAliases: X<Bar> | Y<Baz> | Z<Kwah>;
48+
49+
thingOfTypeAliases = x;
50+
thingOfTypeAliases = y;
51+
thingOfTypeAliases = z;
52+
53+
//// [unionTypeErrorMessageTypeRefs01.js]
54+
thingOfInterfaces = a;
55+
thingOfInterfaces = b;
56+
thingOfInterfaces = c;
57+
thingOfTypeAliases = x;
58+
thingOfTypeAliases = y;
59+
thingOfTypeAliases = z;
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
=== tests/cases/compiler/unionTypeErrorMessageTypeRefs01.ts ===
2+
interface Foo { foo: any }
3+
>Foo : Symbol(Foo, Decl(unionTypeErrorMessageTypeRefs01.ts, 0, 0))
4+
>foo : Symbol(Foo.foo, Decl(unionTypeErrorMessageTypeRefs01.ts, 0, 15))
5+
6+
interface Bar { bar: any }
7+
>Bar : Symbol(Bar, Decl(unionTypeErrorMessageTypeRefs01.ts, 0, 26))
8+
>bar : Symbol(Bar.bar, Decl(unionTypeErrorMessageTypeRefs01.ts, 1, 15))
9+
10+
interface Baz { baz: any }
11+
>Baz : Symbol(Baz, Decl(unionTypeErrorMessageTypeRefs01.ts, 1, 26))
12+
>baz : Symbol(Baz.baz, Decl(unionTypeErrorMessageTypeRefs01.ts, 2, 15))
13+
14+
interface Kwah { kwah: any }
15+
>Kwah : Symbol(Kwah, Decl(unionTypeErrorMessageTypeRefs01.ts, 2, 26))
16+
>kwah : Symbol(Kwah.kwah, Decl(unionTypeErrorMessageTypeRefs01.ts, 3, 16))
17+
18+
////////
19+
20+
interface A<T> {
21+
>A : Symbol(A, Decl(unionTypeErrorMessageTypeRefs01.ts, 3, 28))
22+
>T : Symbol(T, Decl(unionTypeErrorMessageTypeRefs01.ts, 7, 12))
23+
24+
aProp: T;
25+
>aProp : Symbol(A.aProp, Decl(unionTypeErrorMessageTypeRefs01.ts, 7, 16))
26+
>T : Symbol(T, Decl(unionTypeErrorMessageTypeRefs01.ts, 7, 12))
27+
}
28+
29+
interface B<T> {
30+
>B : Symbol(B, Decl(unionTypeErrorMessageTypeRefs01.ts, 9, 1))
31+
>T : Symbol(T, Decl(unionTypeErrorMessageTypeRefs01.ts, 11, 12))
32+
33+
bProp: T;
34+
>bProp : Symbol(B.bProp, Decl(unionTypeErrorMessageTypeRefs01.ts, 11, 16))
35+
>T : Symbol(T, Decl(unionTypeErrorMessageTypeRefs01.ts, 11, 12))
36+
}
37+
38+
interface C<T> {
39+
>C : Symbol(C, Decl(unionTypeErrorMessageTypeRefs01.ts, 13, 1))
40+
>T : Symbol(T, Decl(unionTypeErrorMessageTypeRefs01.ts, 15, 12))
41+
42+
cProp: T;
43+
>cProp : Symbol(C.cProp, Decl(unionTypeErrorMessageTypeRefs01.ts, 15, 16))
44+
>T : Symbol(T, Decl(unionTypeErrorMessageTypeRefs01.ts, 15, 12))
45+
}
46+
47+
declare const a: A<Foo>;
48+
>a : Symbol(a, Decl(unionTypeErrorMessageTypeRefs01.ts, 19, 13))
49+
>A : Symbol(A, Decl(unionTypeErrorMessageTypeRefs01.ts, 3, 28))
50+
>Foo : Symbol(Foo, Decl(unionTypeErrorMessageTypeRefs01.ts, 0, 0))
51+
52+
declare const b: B<Foo>;
53+
>b : Symbol(b, Decl(unionTypeErrorMessageTypeRefs01.ts, 20, 13))
54+
>B : Symbol(B, Decl(unionTypeErrorMessageTypeRefs01.ts, 9, 1))
55+
>Foo : Symbol(Foo, Decl(unionTypeErrorMessageTypeRefs01.ts, 0, 0))
56+
57+
declare const c: C<Foo>;
58+
>c : Symbol(c, Decl(unionTypeErrorMessageTypeRefs01.ts, 21, 13))
59+
>C : Symbol(C, Decl(unionTypeErrorMessageTypeRefs01.ts, 13, 1))
60+
>Foo : Symbol(Foo, Decl(unionTypeErrorMessageTypeRefs01.ts, 0, 0))
61+
62+
declare let thingOfInterfaces: A<Bar> | B<Baz> | C<Kwah>;
63+
>thingOfInterfaces : Symbol(thingOfInterfaces, Decl(unionTypeErrorMessageTypeRefs01.ts, 22, 11))
64+
>A : Symbol(A, Decl(unionTypeErrorMessageTypeRefs01.ts, 3, 28))
65+
>Bar : Symbol(Bar, Decl(unionTypeErrorMessageTypeRefs01.ts, 0, 26))
66+
>B : Symbol(B, Decl(unionTypeErrorMessageTypeRefs01.ts, 9, 1))
67+
>Baz : Symbol(Baz, Decl(unionTypeErrorMessageTypeRefs01.ts, 1, 26))
68+
>C : Symbol(C, Decl(unionTypeErrorMessageTypeRefs01.ts, 13, 1))
69+
>Kwah : Symbol(Kwah, Decl(unionTypeErrorMessageTypeRefs01.ts, 2, 26))
70+
71+
thingOfInterfaces = a;
72+
>thingOfInterfaces : Symbol(thingOfInterfaces, Decl(unionTypeErrorMessageTypeRefs01.ts, 22, 11))
73+
>a : Symbol(a, Decl(unionTypeErrorMessageTypeRefs01.ts, 19, 13))
74+
75+
thingOfInterfaces = b;
76+
>thingOfInterfaces : Symbol(thingOfInterfaces, Decl(unionTypeErrorMessageTypeRefs01.ts, 22, 11))
77+
>b : Symbol(b, Decl(unionTypeErrorMessageTypeRefs01.ts, 20, 13))
78+
79+
thingOfInterfaces = c;
80+
>thingOfInterfaces : Symbol(thingOfInterfaces, Decl(unionTypeErrorMessageTypeRefs01.ts, 22, 11))
81+
>c : Symbol(c, Decl(unionTypeErrorMessageTypeRefs01.ts, 21, 13))
82+
83+
////////
84+
85+
type X<T> = {
86+
>X : Symbol(X, Decl(unionTypeErrorMessageTypeRefs01.ts, 26, 22))
87+
>T : Symbol(T, Decl(unionTypeErrorMessageTypeRefs01.ts, 30, 7))
88+
89+
xProp: T;
90+
>xProp : Symbol(xProp, Decl(unionTypeErrorMessageTypeRefs01.ts, 30, 13))
91+
>T : Symbol(T, Decl(unionTypeErrorMessageTypeRefs01.ts, 30, 7))
92+
}
93+
94+
type Y<T> = {
95+
>Y : Symbol(Y, Decl(unionTypeErrorMessageTypeRefs01.ts, 32, 1))
96+
>T : Symbol(T, Decl(unionTypeErrorMessageTypeRefs01.ts, 34, 7))
97+
98+
yProp: T;
99+
>yProp : Symbol(yProp, Decl(unionTypeErrorMessageTypeRefs01.ts, 34, 13))
100+
>T : Symbol(T, Decl(unionTypeErrorMessageTypeRefs01.ts, 34, 7))
101+
}
102+
103+
type Z<T> = {
104+
>Z : Symbol(Z, Decl(unionTypeErrorMessageTypeRefs01.ts, 36, 1))
105+
>T : Symbol(T, Decl(unionTypeErrorMessageTypeRefs01.ts, 38, 7))
106+
107+
zProp: T;
108+
>zProp : Symbol(zProp, Decl(unionTypeErrorMessageTypeRefs01.ts, 38, 13))
109+
>T : Symbol(T, Decl(unionTypeErrorMessageTypeRefs01.ts, 38, 7))
110+
}
111+
112+
declare const x: X<Foo>;
113+
>x : Symbol(x, Decl(unionTypeErrorMessageTypeRefs01.ts, 42, 13))
114+
>X : Symbol(X, Decl(unionTypeErrorMessageTypeRefs01.ts, 26, 22))
115+
>Foo : Symbol(Foo, Decl(unionTypeErrorMessageTypeRefs01.ts, 0, 0))
116+
117+
declare const y: Y<Foo>;
118+
>y : Symbol(y, Decl(unionTypeErrorMessageTypeRefs01.ts, 43, 13))
119+
>Y : Symbol(Y, Decl(unionTypeErrorMessageTypeRefs01.ts, 32, 1))
120+
>Foo : Symbol(Foo, Decl(unionTypeErrorMessageTypeRefs01.ts, 0, 0))
121+
122+
declare const z: Z<Foo>;
123+
>z : Symbol(z, Decl(unionTypeErrorMessageTypeRefs01.ts, 44, 13))
124+
>Z : Symbol(Z, Decl(unionTypeErrorMessageTypeRefs01.ts, 36, 1))
125+
>Foo : Symbol(Foo, Decl(unionTypeErrorMessageTypeRefs01.ts, 0, 0))
126+
127+
declare let thingOfTypeAliases: X<Bar> | Y<Baz> | Z<Kwah>;
128+
>thingOfTypeAliases : Symbol(thingOfTypeAliases, Decl(unionTypeErrorMessageTypeRefs01.ts, 45, 11))
129+
>X : Symbol(X, Decl(unionTypeErrorMessageTypeRefs01.ts, 26, 22))
130+
>Bar : Symbol(Bar, Decl(unionTypeErrorMessageTypeRefs01.ts, 0, 26))
131+
>Y : Symbol(Y, Decl(unionTypeErrorMessageTypeRefs01.ts, 32, 1))
132+
>Baz : Symbol(Baz, Decl(unionTypeErrorMessageTypeRefs01.ts, 1, 26))
133+
>Z : Symbol(Z, Decl(unionTypeErrorMessageTypeRefs01.ts, 36, 1))
134+
>Kwah : Symbol(Kwah, Decl(unionTypeErrorMessageTypeRefs01.ts, 2, 26))
135+
136+
thingOfTypeAliases = x;
137+
>thingOfTypeAliases : Symbol(thingOfTypeAliases, Decl(unionTypeErrorMessageTypeRefs01.ts, 45, 11))
138+
>x : Symbol(x, Decl(unionTypeErrorMessageTypeRefs01.ts, 42, 13))
139+
140+
thingOfTypeAliases = y;
141+
>thingOfTypeAliases : Symbol(thingOfTypeAliases, Decl(unionTypeErrorMessageTypeRefs01.ts, 45, 11))
142+
>y : Symbol(y, Decl(unionTypeErrorMessageTypeRefs01.ts, 43, 13))
143+
144+
thingOfTypeAliases = z;
145+
>thingOfTypeAliases : Symbol(thingOfTypeAliases, Decl(unionTypeErrorMessageTypeRefs01.ts, 45, 11))
146+
>z : Symbol(z, Decl(unionTypeErrorMessageTypeRefs01.ts, 44, 13))
147+

0 commit comments

Comments
 (0)