From 6a244b9058d2b04985bb973d4af904311745a578 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 27 Mar 2019 23:18:49 -0700 Subject: [PATCH 1/4] Added test. --- .../errorMessageOnIntersectionsWithDiscriminants01.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts 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; From 69affb7f289df4ad5dba16e6af4a3532c7cff0aa Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 27 Mar 2019 23:32:00 -0700 Subject: [PATCH 2/4] Accepted baselines. --- ...ntersectionsWithDiscriminants01.errors.txt | 25 +++++++++++++++++ ...OnIntersectionsWithDiscriminants01.symbols | 28 +++++++++++++++++++ ...geOnIntersectionsWithDiscriminants01.types | 27 ++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.errors.txt create mode 100644 tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.symbols create mode 100644 tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.types diff --git a/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.errors.txt b/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.errors.txt new file mode 100644 index 00000000000..1ac471997d3 --- /dev/null +++ b/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.errors.txt @@ -0,0 +1,25 @@ +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: false; } & { bar: 1; }'. + Type '{ test: true; } & { foo: 1; }' is not assignable to type '{ test: false; }'. + Types of property 'test' are incompatible. + Type 'true' is not assignable to type 'false'. + + +==== 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: false; } & { bar: 1; }'. +!!! error TS2322: Type '{ test: true; } & { foo: 1; }' is not assignable to type '{ test: false; }'. +!!! error TS2322: Types of property 'test' are incompatible. +!!! error TS2322: Type 'true' is not assignable to type 'false'. + \ 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 + From 74d3e2a3efc5071de0b2b8c6589b756b5806fd6b Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 27 Mar 2019 23:41:37 -0700 Subject: [PATCH 3/4] Generalize to intersection types when looking for discriminants in error reporting. --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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) { From 081637f2f8aceb9a01c00582de87db22c94b46ad Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 27 Mar 2019 23:42:20 -0700 Subject: [PATCH 4/4] Accepted baselines. --- ...ageOnIntersectionsWithDiscriminants01.errors.txt | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.errors.txt b/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.errors.txt index 1ac471997d3..1acdc1587f4 100644 --- a/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.errors.txt +++ b/tests/baselines/reference/errorMessageOnIntersectionsWithDiscriminants01.errors.txt @@ -1,9 +1,7 @@ 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: false; } & { bar: 1; }'. - Type '{ test: true; } & { foo: 1; }' is not assignable to type '{ test: false; }'. - Types of property 'test' are incompatible. - Type 'true' is not assignable to type 'false'. + 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) ==== @@ -18,8 +16,7 @@ tests/cases/compiler/errorMessageOnIntersectionsWithDiscriminants01.ts(8,1): err ~ !!! 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: false; } & { bar: 1; }'. -!!! error TS2322: Type '{ test: true; } & { foo: 1; }' is not assignable to type '{ test: false; }'. -!!! error TS2322: Types of property 'test' are incompatible. -!!! error TS2322: Type 'true' is not assignable to type 'false'. +!!! 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