diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ed05cf0a52e..da22fecfb8d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11977,7 +11977,7 @@ namespace ts { matchingCount = Infinity; } else if (overlap.flags & TypeFlags.Union) { - // Some subset overlap if we have only string literals. + // We only want to account for literal types otherwise. // If we have a union of index types, it seems likely that we // needed to elaborate between two generic mapped types anyway. const len = length(filter((overlap as UnionType).types, isUnitType)); @@ -11986,7 +11986,7 @@ namespace ts { matchingCount = len; } } - else if (!(overlap.flags & TypeFlags.Never) && 1 >= matchingCount) { + else if (isUnitType(overlap) && 1 >= matchingCount) { bestMatch = target; matchingCount = 1; } diff --git a/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.errors.txt b/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.errors.txt index 3944c430f33..1b8dab19b5b 100644 --- a/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.errors.txt +++ b/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.errors.txt @@ -8,9 +8,17 @@ tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts(19,3): error TS2345 Type 'string' is not assignable to type 'number'. tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts(24,5): error TS2345: Argument of type '{ a: string; b: string; }' is not assignable to parameter of type 'Bar | Other'. Object literal may only specify known properties, and 'a' does not exist in type 'Bar | Other'. +tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts(42,10): error TS2345: Argument of type '{ dog: string; }' is not assignable to parameter of type 'ExoticAnimal'. + Property 'cat' is missing in type '{ dog: string; }' but required in type 'CatDog'. +tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts(43,10): error TS2345: Argument of type '{ man: string; bear: string; }' is not assignable to parameter of type 'ExoticAnimal'. + Property 'pig' is missing in type '{ man: string; bear: string; }' but required in type 'ManBearPig'. +tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts(46,26): error TS2345: Argument of type '{ man: string; beer: string; }' is not assignable to parameter of type 'ExoticAnimal'. + Object literal may only specify known properties, and 'beer' does not exist in type 'ExoticAnimal'. +tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts(47,10): error TS2345: Argument of type '{ man: string; beer: string; }' is not assignable to parameter of type 'ExoticAnimal'. + Type '{ man: string; beer: string; }' is missing the following properties from type 'ManBearPig': bear, pig -==== tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts (3 errors) ==== +==== tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts (7 errors) ==== interface Foo { a: string; b: number; @@ -53,4 +61,35 @@ tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts(24,5): error TS2345 h(x); h({ a: '', b: '' }) - \ No newline at end of file + + interface CatDog { cat: any, dog: any } + interface ManBearPig { man: any, bear: any, pig: any } + interface Platypus { platypus: any } + + type ExoticAnimal = + | CatDog + | ManBearPig + | Platypus; + + declare function addToZoo(animal: ExoticAnimal): void; + + addToZoo({ dog: "Barky McBarkface" }); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '{ dog: string; }' is not assignable to parameter of type 'ExoticAnimal'. +!!! error TS2345: Property 'cat' is missing in type '{ dog: string; }' but required in type 'CatDog'. +!!! related TS2728 tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts:31:20: 'cat' is declared here. + addToZoo({ man: "Manny", bear: "Coffee" }); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '{ man: string; bear: string; }' is not assignable to parameter of type 'ExoticAnimal'. +!!! error TS2345: Property 'pig' is missing in type '{ man: string; bear: string; }' but required in type 'ManBearPig'. +!!! related TS2728 tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts:32:45: 'pig' is declared here. + + const manBeer = { man: "Manny", beer: "Coffee" }; + addToZoo({ man: "Manny", beer: "Coffee" }); + ~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type '{ man: string; beer: string; }' is not assignable to parameter of type 'ExoticAnimal'. +!!! error TS2345: Object literal may only specify known properties, and 'beer' does not exist in type 'ExoticAnimal'. + addToZoo(manBeer); + ~~~~~~~ +!!! error TS2345: Argument of type '{ man: string; beer: string; }' is not assignable to parameter of type 'ExoticAnimal'. +!!! error TS2345: Type '{ man: string; beer: string; }' is missing the following properties from type 'ManBearPig': bear, pig \ No newline at end of file diff --git a/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.js b/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.js index 36824508b12..a5d63d76f21 100644 --- a/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.js +++ b/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.js @@ -28,7 +28,24 @@ declare function h(x: Foo | Bar | Other): any; h(x); h({ a: '', b: '' }) - + +interface CatDog { cat: any, dog: any } +interface ManBearPig { man: any, bear: any, pig: any } +interface Platypus { platypus: any } + +type ExoticAnimal = + | CatDog + | ManBearPig + | Platypus; + +declare function addToZoo(animal: ExoticAnimal): void; + +addToZoo({ dog: "Barky McBarkface" }); +addToZoo({ man: "Manny", bear: "Coffee" }); + +const manBeer = { man: "Manny", beer: "Coffee" }; +addToZoo({ man: "Manny", beer: "Coffee" }); +addToZoo(manBeer); //// [errorsOnUnionsOfOverlappingObjects01.js] "use strict"; @@ -41,3 +58,8 @@ g(exports.x); g({ a: '', b: '' }); h(exports.x); h({ a: '', b: '' }); +addToZoo({ dog: "Barky McBarkface" }); +addToZoo({ man: "Manny", bear: "Coffee" }); +var manBeer = { man: "Manny", beer: "Coffee" }; +addToZoo({ man: "Manny", beer: "Coffee" }); +addToZoo(manBeer); diff --git a/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.symbols b/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.symbols index 0ce5d6fd2d4..b92f2e895f6 100644 --- a/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.symbols +++ b/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.symbols @@ -75,3 +75,58 @@ h({ a: '', b: '' }) >a : Symbol(a, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 28, 3)) >b : Symbol(b, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 28, 10)) +interface CatDog { cat: any, dog: any } +>CatDog : Symbol(CatDog, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 28, 19)) +>cat : Symbol(CatDog.cat, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 30, 18)) +>dog : Symbol(CatDog.dog, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 30, 28)) + +interface ManBearPig { man: any, bear: any, pig: any } +>ManBearPig : Symbol(ManBearPig, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 30, 39)) +>man : Symbol(ManBearPig.man, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 31, 22)) +>bear : Symbol(ManBearPig.bear, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 31, 32)) +>pig : Symbol(ManBearPig.pig, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 31, 43)) + +interface Platypus { platypus: any } +>Platypus : Symbol(Platypus, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 31, 54)) +>platypus : Symbol(Platypus.platypus, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 32, 20)) + +type ExoticAnimal = +>ExoticAnimal : Symbol(ExoticAnimal, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 32, 36)) + + | CatDog +>CatDog : Symbol(CatDog, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 28, 19)) + + | ManBearPig +>ManBearPig : Symbol(ManBearPig, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 30, 39)) + + | Platypus; +>Platypus : Symbol(Platypus, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 31, 54)) + +declare function addToZoo(animal: ExoticAnimal): void; +>addToZoo : Symbol(addToZoo, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 37, 15)) +>animal : Symbol(animal, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 39, 26)) +>ExoticAnimal : Symbol(ExoticAnimal, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 32, 36)) + +addToZoo({ dog: "Barky McBarkface" }); +>addToZoo : Symbol(addToZoo, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 37, 15)) +>dog : Symbol(dog, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 41, 10)) + +addToZoo({ man: "Manny", bear: "Coffee" }); +>addToZoo : Symbol(addToZoo, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 37, 15)) +>man : Symbol(man, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 42, 10)) +>bear : Symbol(bear, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 42, 24)) + +const manBeer = { man: "Manny", beer: "Coffee" }; +>manBeer : Symbol(manBeer, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 44, 5)) +>man : Symbol(man, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 44, 17)) +>beer : Symbol(beer, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 44, 31)) + +addToZoo({ man: "Manny", beer: "Coffee" }); +>addToZoo : Symbol(addToZoo, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 37, 15)) +>man : Symbol(man, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 45, 10)) +>beer : Symbol(beer, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 45, 24)) + +addToZoo(manBeer); +>addToZoo : Symbol(addToZoo, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 37, 15)) +>manBeer : Symbol(manBeer, Decl(errorsOnUnionsOfOverlappingObjects01.ts, 44, 5)) + diff --git a/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.types b/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.types index a860897d1fa..1e9b1b8c5ef 100644 --- a/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.types +++ b/tests/baselines/reference/errorsOnUnionsOfOverlappingObjects01.types @@ -80,3 +80,64 @@ h({ a: '', b: '' }) >b : string >'' : "" +interface CatDog { cat: any, dog: any } +>cat : any +>dog : any + +interface ManBearPig { man: any, bear: any, pig: any } +>man : any +>bear : any +>pig : any + +interface Platypus { platypus: any } +>platypus : any + +type ExoticAnimal = +>ExoticAnimal : ExoticAnimal + + | CatDog + | ManBearPig + | Platypus; + +declare function addToZoo(animal: ExoticAnimal): void; +>addToZoo : (animal: ExoticAnimal) => void +>animal : ExoticAnimal + +addToZoo({ dog: "Barky McBarkface" }); +>addToZoo({ dog: "Barky McBarkface" }) : void +>addToZoo : (animal: ExoticAnimal) => void +>{ dog: "Barky McBarkface" } : { dog: string; } +>dog : string +>"Barky McBarkface" : "Barky McBarkface" + +addToZoo({ man: "Manny", bear: "Coffee" }); +>addToZoo({ man: "Manny", bear: "Coffee" }) : void +>addToZoo : (animal: ExoticAnimal) => void +>{ man: "Manny", bear: "Coffee" } : { man: string; bear: string; } +>man : string +>"Manny" : "Manny" +>bear : string +>"Coffee" : "Coffee" + +const manBeer = { man: "Manny", beer: "Coffee" }; +>manBeer : { man: string; beer: string; } +>{ man: "Manny", beer: "Coffee" } : { man: string; beer: string; } +>man : string +>"Manny" : "Manny" +>beer : string +>"Coffee" : "Coffee" + +addToZoo({ man: "Manny", beer: "Coffee" }); +>addToZoo({ man: "Manny", beer: "Coffee" }) : void +>addToZoo : (animal: ExoticAnimal) => void +>{ man: "Manny", beer: "Coffee" } : { man: string; beer: string; } +>man : string +>"Manny" : "Manny" +>beer : string +>"Coffee" : "Coffee" + +addToZoo(manBeer); +>addToZoo(manBeer) : void +>addToZoo : (animal: ExoticAnimal) => void +>manBeer : { man: string; beer: string; } + diff --git a/tests/baselines/reference/unionTypeWithRecursiveSubtypeReduction2.errors.txt b/tests/baselines/reference/unionTypeWithRecursiveSubtypeReduction2.errors.txt index a849878087f..1bd7a693966 100644 --- a/tests/baselines/reference/unionTypeWithRecursiveSubtypeReduction2.errors.txt +++ b/tests/baselines/reference/unionTypeWithRecursiveSubtypeReduction2.errors.txt @@ -5,7 +5,11 @@ tests/cases/compiler/unionTypeWithRecursiveSubtypeReduction2.ts(19,1): error TS2 tests/cases/compiler/unionTypeWithRecursiveSubtypeReduction2.ts(20,1): error TS2322: Type 'Class' is not assignable to type 'Property'. Types of property 'parent' are incompatible. Type 'Namespace' is not assignable to type 'Module | Class'. - Property 'parent' is missing in type 'Namespace' but required in type 'Class'. + Type 'Namespace' is not assignable to type 'Module'. + Types of property 'members' are incompatible. + Type '(Class | Property)[]' is not assignable to type 'Class[]'. + Type 'Class | Property' is not assignable to type 'Class'. + Type 'Property' is not assignable to type 'Class'. ==== tests/cases/compiler/unionTypeWithRecursiveSubtypeReduction2.ts (2 errors) ==== @@ -39,6 +43,9 @@ tests/cases/compiler/unionTypeWithRecursiveSubtypeReduction2.ts(20,1): error TS2 !!! error TS2322: Type 'Class' is not assignable to type 'Property'. !!! error TS2322: Types of property 'parent' are incompatible. !!! error TS2322: Type 'Namespace' is not assignable to type 'Module | Class'. -!!! error TS2322: Property 'parent' is missing in type 'Namespace' but required in type 'Class'. -!!! related TS2728 tests/cases/compiler/unionTypeWithRecursiveSubtypeReduction2.ts:10:12: 'parent' is declared here. +!!! error TS2322: Type 'Namespace' is not assignable to type 'Module'. +!!! error TS2322: Types of property 'members' are incompatible. +!!! error TS2322: Type '(Class | Property)[]' is not assignable to type 'Class[]'. +!!! error TS2322: Type 'Class | Property' is not assignable to type 'Class'. +!!! error TS2322: Type 'Property' is not assignable to type 'Class'. \ No newline at end of file diff --git a/tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts b/tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts index aec1821c162..fe1d63cb606 100644 --- a/tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts +++ b/tests/cases/compiler/errorsOnUnionsOfOverlappingObjects01.ts @@ -27,3 +27,21 @@ declare function h(x: Foo | Bar | Other): any; h(x); h({ a: '', b: '' }) + +interface CatDog { cat: any, dog: any } +interface ManBearPig { man: any, bear: any, pig: any } +interface Platypus { platypus: any } + +type ExoticAnimal = + | CatDog + | ManBearPig + | Platypus; + +declare function addToZoo(animal: ExoticAnimal): void; + +addToZoo({ dog: "Barky McBarkface" }); +addToZoo({ man: "Manny", bear: "Coffee" }); + +const manBeer = { man: "Manny", beer: "Coffee" }; +addToZoo({ man: "Manny", beer: "Coffee" }); +addToZoo(manBeer); \ No newline at end of file