Merge pull request #25781 from Microsoft/objectsAgainstArrays-3.0

[release 3.0] Avoid elaborating object literals against array-likes
This commit is contained in:
Daniel Rosenwasser
2018-07-19 08:07:26 -07:00
committed by GitHub
6 changed files with 124 additions and 1 deletions

View File

@@ -11182,7 +11182,8 @@ namespace ts {
if (reportErrors) {
const bestMatchingType =
findMatchingDiscriminantType(source, target) ||
findMatchingTypeReferenceOrTypeAliasReference(source, target);
findMatchingTypeReferenceOrTypeAliasReference(source, target) ||
findBestTypeForObjectLiteral(source, target);
isRelatedTo(source, bestMatchingType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true);
}
@@ -11207,6 +11208,11 @@ namespace ts {
}
}
function findBestTypeForObjectLiteral(source: Type, unionTarget: UnionOrIntersectionType) {
if (getObjectFlags(source) & ObjectFlags.ObjectLiteral && forEachType(unionTarget, isArrayLikeType)) {
return find(unionTarget.types, t => !isArrayLikeType(t));
}
}
// Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly
function findMatchingDiscriminantType(source: Type, target: UnionOrIntersectionType) {

View File

@@ -0,0 +1,30 @@
tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts(9,5): error TS2322: Type '{ bar: { prop: number; }; }[]' is not assignable to type 'Foo[]'.
Type '{ bar: { prop: number; }; }' is not assignable to type 'Foo'.
Types of property 'bar' are incompatible.
Type '{ prop: number; }' is not assignable to type 'Bar | Bar[]'.
Type '{ prop: number; }' is not assignable to type 'Bar'.
Types of property 'prop' are incompatible.
Type 'number' is not assignable to type 'string'.
==== tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts (1 errors) ====
interface Foo {
bar: Bar | Bar[];
}
interface Bar {
prop: string;
}
let x: Foo[] = [
~
!!! error TS2322: Type '{ bar: { prop: number; }; }[]' is not assignable to type 'Foo[]'.
!!! error TS2322: Type '{ bar: { prop: number; }; }' is not assignable to type 'Foo'.
!!! error TS2322: Types of property 'bar' are incompatible.
!!! error TS2322: Type '{ prop: number; }' is not assignable to type 'Bar | Bar[]'.
!!! error TS2322: Type '{ prop: number; }' is not assignable to type 'Bar'.
!!! error TS2322: Types of property 'prop' are incompatible.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
{ bar: { prop: 100 } }
]

View File

@@ -0,0 +1,18 @@
//// [objectLiteralsAgainstUnionsOfArrays01.ts]
interface Foo {
bar: Bar | Bar[];
}
interface Bar {
prop: string;
}
let x: Foo[] = [
{ bar: { prop: 100 } }
]
//// [objectLiteralsAgainstUnionsOfArrays01.js]
var x = [
{ bar: { prop: 100 } }
];

View File

@@ -0,0 +1,27 @@
=== tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts ===
interface Foo {
>Foo : Symbol(Foo, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 0, 0))
bar: Bar | Bar[];
>bar : Symbol(Foo.bar, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 0, 15))
>Bar : Symbol(Bar, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 2, 1))
>Bar : Symbol(Bar, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 2, 1))
}
interface Bar {
>Bar : Symbol(Bar, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 2, 1))
prop: string;
>prop : Symbol(Bar.prop, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 4, 15))
}
let x: Foo[] = [
>x : Symbol(x, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 8, 3))
>Foo : Symbol(Foo, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 0, 0))
{ bar: { prop: 100 } }
>bar : Symbol(bar, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 9, 3))
>prop : Symbol(prop, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 9, 10))
]

View File

@@ -0,0 +1,31 @@
=== tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts ===
interface Foo {
>Foo : Foo
bar: Bar | Bar[];
>bar : Bar | Bar[]
>Bar : Bar
>Bar : Bar
}
interface Bar {
>Bar : Bar
prop: string;
>prop : string
}
let x: Foo[] = [
>x : Foo[]
>Foo : Foo
>[ { bar: { prop: 100 } }] : { bar: { prop: number; }; }[]
{ bar: { prop: 100 } }
>{ bar: { prop: 100 } } : { bar: { prop: number; }; }
>bar : { prop: number; }
>{ prop: 100 } : { prop: number; }
>prop : number
>100 : 100
]

View File

@@ -0,0 +1,11 @@
interface Foo {
bar: Bar | Bar[];
}
interface Bar {
prop: string;
}
let x: Foo[] = [
{ bar: { prop: 100 } }
]