Merge pull request #30626 from Microsoft/discriminantFromIntersectionErrors

Better discriminant property errors on intersections
This commit is contained in:
Daniel Rosenwasser
2019-03-28 14:15:14 -04:00
committed by GitHub
5 changed files with 89 additions and 2 deletions

View File

@@ -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) {

View File

@@ -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.

View File

@@ -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))

View File

@@ -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

View File

@@ -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;