diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 98a459b6ccd..fe1f05c4020 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -12533,8 +12533,8 @@ namespace ts { // Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly function findMatchingDiscriminantType(source: Type, target: Type) { - if (target.flags & TypeFlags.Union) { - const sourceProperties = getPropertiesOfObjectType(source); + if (target.flags & TypeFlags.Union && source.flags & (TypeFlags.Intersection | TypeFlags.Object)) { + const sourceProperties = getPropertiesOfType(source); if (sourceProperties) { const sourcePropertiesFiltered = findDiscriminantProperties(sourceProperties, target); if (sourcePropertiesFiltered) { diff --git a/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.errors.txt b/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.errors.txt new file mode 100644 index 00000000000..1acdc1587f4 --- /dev/null +++ b/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.errors.txt @@ -0,0 +1,22 @@ +tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts(8,1): error TS2322: Type 'A' is not assignable to type 'B'. + Type '{ test: true; } & { foo: 1; }' is not assignable to type 'B'. + Type '{ test: true; } & { foo: 1; }' is not assignable to type '{ test: true; } & { bar: 1; }'. + Property 'bar' is missing in type '{ test: true; } & { foo: 1; }' but required in type '{ bar: 1; }'. + + +==== tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts (1 errors) ==== + export type Common = { test: true } | { test: false }; + export type A = Common & { foo: 1 }; + export type B = Common & { bar: 1 }; + + declare const a: A; + declare let b: B; + + b = a; + ~ +!!! error TS2322: Type 'A' is not assignable to type 'B'. +!!! error TS2322: Type '{ test: true; } & { foo: 1; }' is not assignable to type 'B'. +!!! error TS2322: Type '{ test: true; } & { foo: 1; }' is not assignable to type '{ test: true; } & { bar: 1; }'. +!!! error TS2322: Property 'bar' is missing in type '{ test: true; } & { foo: 1; }' but required in type '{ bar: 1; }'. +!!! related TS2728 tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts:3:28: 'bar' is declared here. + \ No newline at end of file diff --git a/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.symbols b/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.symbols new file mode 100644 index 00000000000..a675f36044b --- /dev/null +++ b/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.symbols @@ -0,0 +1,28 @@ +=== tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts === +export type Common = { test: true } | { test: false }; +>Common : Symbol(Common, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 0, 0)) +>test : Symbol(test, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 0, 22)) +>test : Symbol(test, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 0, 39)) + +export type A = Common & { foo: 1 }; +>A : Symbol(A, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 0, 54)) +>Common : Symbol(Common, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 0, 0)) +>foo : Symbol(foo, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 1, 26)) + +export type B = Common & { bar: 1 }; +>B : Symbol(B, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 1, 36)) +>Common : Symbol(Common, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 0, 0)) +>bar : Symbol(bar, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 2, 26)) + +declare const a: A; +>a : Symbol(a, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 4, 13)) +>A : Symbol(A, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 0, 54)) + +declare let b: B; +>b : Symbol(b, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 5, 11)) +>B : Symbol(B, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 1, 36)) + +b = a; +>b : Symbol(b, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 5, 11)) +>a : Symbol(a, Decl(errorMessageOnIntersectionsWithDiscriminants01.ts, 4, 13)) + diff --git a/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.types b/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.types new file mode 100644 index 00000000000..4c532de4b27 --- /dev/null +++ b/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.types @@ -0,0 +1,27 @@ +=== tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts === +export type Common = { test: true } | { test: false }; +>Common : Common +>test : true +>true : true +>test : false +>false : false + +export type A = Common & { foo: 1 }; +>A : A +>foo : 1 + +export type B = Common & { bar: 1 }; +>B : B +>bar : 1 + +declare const a: A; +>a : A + +declare let b: B; +>b : B + +b = a; +>b = a : A +>b : B +>a : A + diff --git a/tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts b/tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts new file mode 100644 index 00000000000..f41ef632723 --- /dev/null +++ b/tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts @@ -0,0 +1,10 @@ +// @noEmit: true + +export type Common = { test: true } | { test: false }; +export type A = Common & { foo: 1 }; +export type B = Common & { bar: 1 }; + +declare const a: A; +declare let b: B; + +b = a;