Merge pull request #7203 from Microsoft/intersectionErrors

Stop elaborating errors when relating intersection constituents
This commit is contained in:
Daniel Rosenwasser 2016-02-24 16:26:21 -08:00
commit 713c0e0756
15 changed files with 359 additions and 38 deletions

View file

@ -5521,8 +5521,20 @@ namespace ts {
// on either side that need to be prioritized. For example, A | B = (A | B) & (C | D) or
// A & B = (A & B) | (C & D).
if (source.flags & TypeFlags.Intersection) {
// If target is a union type the following check will report errors so we suppress them here
if (result = someTypeRelatedToType(<IntersectionType>source, target, reportErrors && !(target.flags & TypeFlags.Union))) {
// Check to see if any constituents of the intersection are immediately related to the target.
//
// Don't report errors though. Checking whether a constituent is related to the source is not actually
// useful and leads to some confusing error messages. Instead it is better to let the below checks
// take care of this, or to not elaborate at all. For instance,
//
// - For an object type (such as 'C = A & B'), users are usually more interested in structural errors.
//
// - For a union type (such as '(A | B) = (C & D)'), it's better to hold onto the whole intersection
// than to report that 'D' is not assignable to 'A' or 'B'.
//
// - For a primitive type or type parameter (such as 'number = A & B') there is no point in
// breaking the intersection apart.
if (result = someTypeRelatedToType(<IntersectionType>source, target, /*reportErrors*/ false)) {
return result;
}
}

View file

@ -0,0 +1,26 @@
tests/cases/compiler/errorMessagesIntersectionTypes01.ts(14,5): error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'.
Types of property 'fooProp' are incompatible.
Type 'string' is not assignable to type 'boolean'.
==== tests/cases/compiler/errorMessagesIntersectionTypes01.ts (1 errors) ====
interface Foo {
fooProp: boolean;
}
interface Bar {
barProp: string;
}
interface FooBar extends Foo, Bar {
}
declare function mixBar<T>(obj: T): T & Bar;
let fooBar: FooBar = mixBar({
~~~~~~
!!! error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'.
!!! error TS2322: Types of property 'fooProp' are incompatible.
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
fooProp: "frizzlebizzle"
});

View file

@ -0,0 +1,22 @@
//// [errorMessagesIntersectionTypes01.ts]
interface Foo {
fooProp: boolean;
}
interface Bar {
barProp: string;
}
interface FooBar extends Foo, Bar {
}
declare function mixBar<T>(obj: T): T & Bar;
let fooBar: FooBar = mixBar({
fooProp: "frizzlebizzle"
});
//// [errorMessagesIntersectionTypes01.js]
var fooBar = mixBar({
fooProp: "frizzlebizzle"
});

View file

@ -0,0 +1,28 @@
tests/cases/compiler/errorMessagesIntersectionTypes02.ts(14,5): error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'.
Types of property 'fooProp' are incompatible.
Type 'string' is not assignable to type '"hello" | "world"'.
Type 'string' is not assignable to type '"world"'.
==== tests/cases/compiler/errorMessagesIntersectionTypes02.ts (1 errors) ====
interface Foo {
fooProp: "hello" | "world";
}
interface Bar {
barProp: string;
}
interface FooBar extends Foo, Bar {
}
declare function mixBar<T>(obj: T): T & Bar;
let fooBar: FooBar = mixBar({
~~~~~~
!!! error TS2322: Type '{ fooProp: string; } & Bar' is not assignable to type 'FooBar'.
!!! error TS2322: Types of property 'fooProp' are incompatible.
!!! error TS2322: Type 'string' is not assignable to type '"hello" | "world"'.
!!! error TS2322: Type 'string' is not assignable to type '"world"'.
fooProp: "frizzlebizzle"
});

View file

@ -0,0 +1,22 @@
//// [errorMessagesIntersectionTypes02.ts]
interface Foo {
fooProp: "hello" | "world";
}
interface Bar {
barProp: string;
}
interface FooBar extends Foo, Bar {
}
declare function mixBar<T>(obj: T): T & Bar;
let fooBar: FooBar = mixBar({
fooProp: "frizzlebizzle"
});
//// [errorMessagesIntersectionTypes02.js]
var fooBar = mixBar({
fooProp: "frizzlebizzle"
});

View file

@ -0,0 +1,42 @@
tests/cases/compiler/errorMessagesIntersectionTypes03.ts(17,5): error TS2322: Type 'A & B' is not assignable to type 'T'.
tests/cases/compiler/errorMessagesIntersectionTypes03.ts(18,5): error TS2322: Type 'A & B' is not assignable to type 'U'.
tests/cases/compiler/errorMessagesIntersectionTypes03.ts(19,5): error TS2322: Type 'A & B' is not assignable to type 'V'.
tests/cases/compiler/errorMessagesIntersectionTypes03.ts(22,5): error TS2322: Type 'T & B' is not assignable to type 'U'.
tests/cases/compiler/errorMessagesIntersectionTypes03.ts(23,5): error TS2322: Type 'T & B' is not assignable to type 'V'.
==== tests/cases/compiler/errorMessagesIntersectionTypes03.ts (5 errors) ====
interface A {
a;
}
interface B {
b;
}
function f<T, U extends A, V extends U>(): void {
let t: T;
let u: U;
let v: V;
let a_and_b: A & B;
let t_and_b: T & B;
t = a_and_b;
~
!!! error TS2322: Type 'A & B' is not assignable to type 'T'.
u = a_and_b;
~
!!! error TS2322: Type 'A & B' is not assignable to type 'U'.
v = a_and_b;
~
!!! error TS2322: Type 'A & B' is not assignable to type 'V'.
t = t_and_b;
u = t_and_b;
~
!!! error TS2322: Type 'T & B' is not assignable to type 'U'.
v = t_and_b;
~
!!! error TS2322: Type 'T & B' is not assignable to type 'V'.
}

View file

@ -0,0 +1,40 @@
//// [errorMessagesIntersectionTypes03.ts]
interface A {
a;
}
interface B {
b;
}
function f<T, U extends A, V extends U>(): void {
let t: T;
let u: U;
let v: V;
let a_and_b: A & B;
let t_and_b: T & B;
t = a_and_b;
u = a_and_b;
v = a_and_b;
t = t_and_b;
u = t_and_b;
v = t_and_b;
}
//// [errorMessagesIntersectionTypes03.js]
function f() {
var t;
var u;
var v;
var a_and_b;
var t_and_b;
t = a_and_b;
u = a_and_b;
v = a_and_b;
t = t_and_b;
u = t_and_b;
v = t_and_b;
}

View file

@ -0,0 +1,37 @@
tests/cases/compiler/errorMessagesIntersectionTypes04.ts(17,5): error TS2322: Type 'A & B' is not assignable to type 'number'.
tests/cases/compiler/errorMessagesIntersectionTypes04.ts(18,5): error TS2322: Type 'A & B' is not assignable to type 'boolean'.
tests/cases/compiler/errorMessagesIntersectionTypes04.ts(19,5): error TS2322: Type 'A & B' is not assignable to type 'string'.
tests/cases/compiler/errorMessagesIntersectionTypes04.ts(21,5): error TS2322: Type 'number & boolean' is not assignable to type 'string'.
==== tests/cases/compiler/errorMessagesIntersectionTypes04.ts (4 errors) ====
interface A {
a;
}
interface B {
b;
}
function f<T, U extends A, V extends U>(): void {
let num: number;
let bool: boolean;
let str: string;
let a_and_b: A & B;
let num_and_bool: number & boolean;
num = a_and_b;
~~~
!!! error TS2322: Type 'A & B' is not assignable to type 'number'.
bool = a_and_b;
~~~~
!!! error TS2322: Type 'A & B' is not assignable to type 'boolean'.
str = a_and_b;
~~~
!!! error TS2322: Type 'A & B' is not assignable to type 'string'.
str = num_and_bool;
~~~
!!! error TS2322: Type 'number & boolean' is not assignable to type 'string'.
}

View file

@ -0,0 +1,36 @@
//// [errorMessagesIntersectionTypes04.ts]
interface A {
a;
}
interface B {
b;
}
function f<T, U extends A, V extends U>(): void {
let num: number;
let bool: boolean;
let str: string;
let a_and_b: A & B;
let num_and_bool: number & boolean;
num = a_and_b;
bool = a_and_b;
str = a_and_b;
str = num_and_bool;
}
//// [errorMessagesIntersectionTypes04.js]
function f() {
var num;
var bool;
var str;
var a_and_b;
var num_and_bool;
num = a_and_b;
bool = a_and_b;
str = a_and_b;
str = num_and_bool;
}

View file

@ -17,27 +17,22 @@ tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(25,1): e
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(26,1): error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'A & B'.
Type 'C & D' is not assignable to type 'A & B'.
Type 'C & D' is not assignable to type 'A'.
Type 'D' is not assignable to type 'A'.
Property 'a' is missing in type 'D'.
Property 'a' is missing in type 'C & D'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(27,1): error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'A | B'.
Type 'C & D' is not assignable to type 'A | B'.
Type 'C & D' is not assignable to type 'B'.
Type 'D' is not assignable to type 'B'.
Property 'b' is missing in type 'D'.
Property 'b' is missing in type 'C & D'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(28,1): error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'C & D'.
Type 'A & B' is not assignable to type 'C & D'.
Type 'A & B' is not assignable to type 'C'.
Type 'B' is not assignable to type 'C'.
Property 'c' is missing in type 'B'.
Property 'c' is missing in type 'A & B'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(29,1): error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'C | D'.
Type 'A & B' is not assignable to type 'C | D'.
Type 'A & B' is not assignable to type 'D'.
Type 'B' is not assignable to type 'D'.
Property 'd' is missing in type 'B'.
Property 'd' is missing in type 'A & B'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(31,1): error TS2322: Type 'A & B' is not assignable to type '(A | B) & (C | D)'.
Type 'A & B' is not assignable to type 'C | D'.
Type 'A & B' is not assignable to type 'D'.
Type 'B' is not assignable to type 'D'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(32,1): error TS2322: Type 'A | B' is not assignable to type '(A | B) & (C | D)'.
Type 'A' is not assignable to type '(A | B) & (C | D)'.
Type 'A' is not assignable to type 'C | D'.
@ -46,7 +41,6 @@ tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(32,1): e
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(33,1): error TS2322: Type 'C & D' is not assignable to type '(A | B) & (C | D)'.
Type 'C & D' is not assignable to type 'A | B'.
Type 'C & D' is not assignable to type 'B'.
Type 'D' is not assignable to type 'B'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(34,1): error TS2322: Type 'C | D' is not assignable to type '(A | B) & (C | D)'.
Type 'C' is not assignable to type '(A | B) & (C | D)'.
Type 'C' is not assignable to type 'A | B'.
@ -54,14 +48,10 @@ tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(34,1): e
Property 'b' is missing in type 'C'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(35,1): error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'A & B'.
Type '(A | B) & (C | D)' is not assignable to type 'A'.
Type 'C | D' is not assignable to type 'A'.
Type 'C' is not assignable to type 'A'.
Property 'a' is missing in type 'C'.
Property 'a' is missing in type '(A | B) & (C | D)'.
tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(37,1): error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'C & D'.
Type '(A | B) & (C | D)' is not assignable to type 'C'.
Type 'C | D' is not assignable to type 'C'.
Type 'D' is not assignable to type 'C'.
Property 'c' is missing in type 'D'.
Property 'c' is missing in type '(A | B) & (C | D)'.
==== tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts (14 errors) ====
@ -115,36 +105,31 @@ tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(37,1): e
!!! error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'A & B'.
!!! error TS2322: Type 'C & D' is not assignable to type 'A & B'.
!!! error TS2322: Type 'C & D' is not assignable to type 'A'.
!!! error TS2322: Type 'D' is not assignable to type 'A'.
!!! error TS2322: Property 'a' is missing in type 'D'.
!!! error TS2322: Property 'a' is missing in type 'C & D'.
aob = x;
~~~
!!! error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'A | B'.
!!! error TS2322: Type 'C & D' is not assignable to type 'A | B'.
!!! error TS2322: Type 'C & D' is not assignable to type 'B'.
!!! error TS2322: Type 'D' is not assignable to type 'B'.
!!! error TS2322: Property 'b' is missing in type 'D'.
!!! error TS2322: Property 'b' is missing in type 'C & D'.
cnd = x;
~~~
!!! error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'C & D'.
!!! error TS2322: Type 'A & B' is not assignable to type 'C & D'.
!!! error TS2322: Type 'A & B' is not assignable to type 'C'.
!!! error TS2322: Type 'B' is not assignable to type 'C'.
!!! error TS2322: Property 'c' is missing in type 'B'.
!!! error TS2322: Property 'c' is missing in type 'A & B'.
cod = x;
~~~
!!! error TS2322: Type '(A & B) | (C & D)' is not assignable to type 'C | D'.
!!! error TS2322: Type 'A & B' is not assignable to type 'C | D'.
!!! error TS2322: Type 'A & B' is not assignable to type 'D'.
!!! error TS2322: Type 'B' is not assignable to type 'D'.
!!! error TS2322: Property 'd' is missing in type 'B'.
!!! error TS2322: Property 'd' is missing in type 'A & B'.
y = anb;
~
!!! error TS2322: Type 'A & B' is not assignable to type '(A | B) & (C | D)'.
!!! error TS2322: Type 'A & B' is not assignable to type 'C | D'.
!!! error TS2322: Type 'A & B' is not assignable to type 'D'.
!!! error TS2322: Type 'B' is not assignable to type 'D'.
y = aob;
~
!!! error TS2322: Type 'A | B' is not assignable to type '(A | B) & (C | D)'.
@ -157,7 +142,6 @@ tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(37,1): e
!!! error TS2322: Type 'C & D' is not assignable to type '(A | B) & (C | D)'.
!!! error TS2322: Type 'C & D' is not assignable to type 'A | B'.
!!! error TS2322: Type 'C & D' is not assignable to type 'B'.
!!! error TS2322: Type 'D' is not assignable to type 'B'.
y = cod;
~
!!! error TS2322: Type 'C | D' is not assignable to type '(A | B) & (C | D)'.
@ -169,16 +153,12 @@ tests/cases/conformance/types/intersection/intersectionAndUnionTypes.ts(37,1): e
~~~
!!! error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'A & B'.
!!! error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'A'.
!!! error TS2322: Type 'C | D' is not assignable to type 'A'.
!!! error TS2322: Type 'C' is not assignable to type 'A'.
!!! error TS2322: Property 'a' is missing in type 'C'.
!!! error TS2322: Property 'a' is missing in type '(A | B) & (C | D)'.
aob = y; // Ok
cnd = y;
~~~
!!! error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'C & D'.
!!! error TS2322: Type '(A | B) & (C | D)' is not assignable to type 'C'.
!!! error TS2322: Type 'C | D' is not assignable to type 'C'.
!!! error TS2322: Type 'D' is not assignable to type 'C'.
!!! error TS2322: Property 'c' is missing in type 'D'.
!!! error TS2322: Property 'c' is missing in type '(A | B) & (C | D)'.
cod = y; // Ok

View file

@ -1,7 +1,6 @@
tests/cases/conformance/types/intersection/recursiveIntersectionTypes.ts(19,1): error TS2322: Type 'Entity & { next: Entity & any; }' is not assignable to type 'Product & { next: Product & any; }'.
Type 'Entity & { next: Entity & any; }' is not assignable to type 'Product'.
Type '{ next: Entity & any; }' is not assignable to type 'Product'.
Property 'price' is missing in type '{ next: Entity & any; }'.
Property 'price' is missing in type 'Entity & { next: Entity & any; }'.
==== tests/cases/conformance/types/intersection/recursiveIntersectionTypes.ts (1 errors) ====
@ -27,6 +26,5 @@ tests/cases/conformance/types/intersection/recursiveIntersectionTypes.ts(19,1):
~~~~~~~~~~~
!!! error TS2322: Type 'Entity & { next: Entity & any; }' is not assignable to type 'Product & { next: Product & any; }'.
!!! error TS2322: Type 'Entity & { next: Entity & any; }' is not assignable to type 'Product'.
!!! error TS2322: Type '{ next: Entity & any; }' is not assignable to type 'Product'.
!!! error TS2322: Property 'price' is missing in type '{ next: Entity & any; }'.
!!! error TS2322: Property 'price' is missing in type 'Entity & { next: Entity & any; }'.

View file

@ -0,0 +1,16 @@
interface Foo {
fooProp: boolean;
}
interface Bar {
barProp: string;
}
interface FooBar extends Foo, Bar {
}
declare function mixBar<T>(obj: T): T & Bar;
let fooBar: FooBar = mixBar({
fooProp: "frizzlebizzle"
});

View file

@ -0,0 +1,16 @@
interface Foo {
fooProp: "hello" | "world";
}
interface Bar {
barProp: string;
}
interface FooBar extends Foo, Bar {
}
declare function mixBar<T>(obj: T): T & Bar;
let fooBar: FooBar = mixBar({
fooProp: "frizzlebizzle"
});

View file

@ -0,0 +1,24 @@
interface A {
a;
}
interface B {
b;
}
function f<T, U extends A, V extends U>(): void {
let t: T;
let u: U;
let v: V;
let a_and_b: A & B;
let t_and_b: T & B;
t = a_and_b;
u = a_and_b;
v = a_and_b;
t = t_and_b;
u = t_and_b;
v = t_and_b;
}

View file

@ -0,0 +1,22 @@
interface A {
a;
}
interface B {
b;
}
function f<T, U extends A, V extends U>(): void {
let num: number;
let bool: boolean;
let str: string;
let a_and_b: A & B;
let num_and_bool: number & boolean;
num = a_and_b;
bool = a_and_b;
str = a_and_b;
str = num_and_bool;
}