Skip to content

Commit f6d7033

Browse files
Merge pull request #30626 from Microsoft/discriminantFromIntersectionErrors
Better discriminant property errors on intersections
2 parents b7881a2 + 081637f commit f6d7033

5 files changed

+89
-2
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12533,8 +12533,8 @@ namespace ts {
1253312533

1253412534
// Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly
1253512535
function findMatchingDiscriminantType(source: Type, target: Type) {
12536-
if (target.flags & TypeFlags.Union) {
12537-
const sourceProperties = getPropertiesOfObjectType(source);
12536+
if (target.flags & TypeFlags.Union && source.flags & (TypeFlags.Intersection | TypeFlags.Object)) {
12537+
const sourceProperties = getPropertiesOfType(source);
1253812538
if (sourceProperties) {
1253912539
const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target);
1254012540
if (sourcePropertiesFiltered) {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts(8,1): error TS2322: Type 'A' is not assignable to type 'B'.
2+
Type '{ test: true; } & { foo: 1; }' is not assignable to type 'B'.
3+
Type '{ test: true; } & { foo: 1; }' is not assignable to type '{ test: true; } & { bar: 1; }'.
4+
Property 'bar' is missing in type '{ test: true; } & { foo: 1; }' but required in type '{ bar: 1; }'.
5+
6+
7+
==== tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts (1 errors) ====
8+
export type Common = { test: true } | { test: false };
9+
export type A = Common & { foo: 1 };
10+
export type B = Common & { bar: 1 };
11+
12+
declare const a: A;
13+
declare let b: B;
14+
15+
b = a;
16+
~
17+
!!! error TS2322: Type 'A' is not assignable to type 'B'.
18+
!!! error TS2322: Type '{ test: true; } & { foo: 1; }' is not assignable to type 'B'.
19+
!!! error TS2322: Type '{ test: true; } & { foo: 1; }' is not assignable to type '{ test: true; } & { bar: 1; }'.
20+
!!! error TS2322: Property 'bar' is missing in type '{ test: true; } & { foo: 1; }' but required in type '{ bar: 1; }'.
21+
!!! related TS2728 tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts:3:28: 'bar' is declared here.
22+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
=== tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts ===
2+
export type Common = { test: true } | { test: false };
3+
>Common : Symbol(Common, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 0, 0))
4+
>test : Symbol(test, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 0, 22))
5+
>test : Symbol(test, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 0, 39))
6+
7+
export type A = Common & { foo: 1 };
8+
>A : Symbol(A, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 0, 54))
9+
>Common : Symbol(Common, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 0, 0))
10+
>foo : Symbol(foo, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 1, 26))
11+
12+
export type B = Common & { bar: 1 };
13+
>B : Symbol(B, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 1, 36))
14+
>Common : Symbol(Common, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 0, 0))
15+
>bar : Symbol(bar, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 2, 26))
16+
17+
declare const a: A;
18+
>a : Symbol(a, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 4, 13))
19+
>A : Symbol(A, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 0, 54))
20+
21+
declare let b: B;
22+
>b : Symbol(b, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 5, 11))
23+
>B : Symbol(B, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 1, 36))
24+
25+
b = a;
26+
>b : Symbol(b, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 5, 11))
27+
>a : Symbol(a, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 4, 13))
28+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
=== tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts ===
2+
export type Common = { test: true } | { test: false };
3+
>Common : Common
4+
>test : true
5+
>true : true
6+
>test : false
7+
>false : false
8+
9+
export type A = Common & { foo: 1 };
10+
>A : A
11+
>foo : 1
12+
13+
export type B = Common & { bar: 1 };
14+
>B : B
15+
>bar : 1
16+
17+
declare const a: A;
18+
>a : A
19+
20+
declare let b: B;
21+
>b : B
22+
23+
b = a;
24+
>b = a : A
25+
>b : B
26+
>a : A
27+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// @noEmit: true
2+
3+
export type Common = { test: true } | { test: false };
4+
export type A = Common & { foo: 1 };
5+
export type B = Common & { bar: 1 };
6+
7+
declare const a: A;
8+
declare let b: B;
9+
10+
b = a;

0 commit comments

Comments
 (0)