Skip to content

Commit ba8330c

Browse files
authored
Merge pull request #14006 from Microsoft/better-discriminated-union-errors
Improve discriminated union error messages
2 parents 58b8a54 + 271ca80 commit ba8330c

File tree

4 files changed

+79
-3
lines changed

4 files changed

+79
-3
lines changed

src/compiler/checker.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7783,16 +7783,36 @@ namespace ts {
77837783
if (target.flags & TypeFlags.Union && containsType(targetTypes, source)) {
77847784
return Ternary.True;
77857785
}
7786-
const len = targetTypes.length;
7787-
for (let i = 0; i < len; i++) {
7788-
const related = isRelatedTo(source, targetTypes[i], reportErrors && i === len - 1);
7786+
for (const type of targetTypes) {
7787+
const related = isRelatedTo(source, type, /*reportErrors*/ false);
77897788
if (related) {
77907789
return related;
77917790
}
77927791
}
7792+
if (reportErrors) {
7793+
const discriminantType = findMatchingDiscriminantType(source, target);
7794+
isRelatedTo(source, discriminantType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true);
7795+
}
77937796
return Ternary.False;
77947797
}
77957798

7799+
function findMatchingDiscriminantType(source: Type, target: UnionOrIntersectionType) {
7800+
const sourceProperties = getPropertiesOfObjectType(source);
7801+
if (sourceProperties) {
7802+
for (const sourceProperty of sourceProperties) {
7803+
if (isDiscriminantProperty(target, sourceProperty.name)) {
7804+
const sourceType = getTypeOfSymbol(sourceProperty);
7805+
for (const type of target.types) {
7806+
const targetType = getTypeOfPropertyOfType(type, sourceProperty.name);
7807+
if (targetType && isRelatedTo(sourceType, targetType)) {
7808+
return type;
7809+
}
7810+
}
7811+
}
7812+
}
7813+
}
7814+
}
7815+
77967816
function typeRelatedToEachType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
77977817
let result = Ternary.True;
77987818
const targetTypes = target.types;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
tests/cases/compiler/discriminatedUnionErrorMessage.ts(8,5): error TS2322: Type '{ kind: "sq"; x: number; y: number; }' is not assignable to type 'Shape'.
2+
Type '{ kind: "sq"; x: number; y: number; }' is not assignable to type 'Square'.
3+
Property 'size' is missing in type '{ kind: "sq"; x: number; y: number; }'.
4+
5+
6+
==== tests/cases/compiler/discriminatedUnionErrorMessage.ts (1 errors) ====
7+
type Square = { kind: "sq", size: number }
8+
type Rectangle = { kind: "rt", x: number, y: number }
9+
type Circle = { kind: "cr", radius: number }
10+
type Shape =
11+
| Square
12+
| Rectangle
13+
| Circle;
14+
let shape: Shape = {
15+
~~~~~
16+
!!! error TS2322: Type '{ kind: "sq"; x: number; y: number; }' is not assignable to type 'Shape'.
17+
!!! error TS2322: Type '{ kind: "sq"; x: number; y: number; }' is not assignable to type 'Square'.
18+
!!! error TS2322: Property 'size' is missing in type '{ kind: "sq"; x: number; y: number; }'.
19+
kind: "sq",
20+
x: 12,
21+
y: 13,
22+
}
23+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
//// [discriminatedUnionErrorMessage.ts]
2+
type Square = { kind: "sq", size: number }
3+
type Rectangle = { kind: "rt", x: number, y: number }
4+
type Circle = { kind: "cr", radius: number }
5+
type Shape =
6+
| Square
7+
| Rectangle
8+
| Circle;
9+
let shape: Shape = {
10+
kind: "sq",
11+
x: 12,
12+
y: 13,
13+
}
14+
15+
16+
//// [discriminatedUnionErrorMessage.js]
17+
var shape = {
18+
kind: "sq",
19+
x: 12,
20+
y: 13
21+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
type Square = { kind: "sq", size: number }
2+
type Rectangle = { kind: "rt", x: number, y: number }
3+
type Circle = { kind: "cr", radius: number }
4+
type Shape =
5+
| Square
6+
| Rectangle
7+
| Circle;
8+
let shape: Shape = {
9+
kind: "sq",
10+
x: 12,
11+
y: 13,
12+
}

0 commit comments

Comments
 (0)