Skip to content

Commit 37277e8

Browse files
Merge pull request #25752 from Microsoft/objectsAgainstArrays
Avoid elaborating object literals against array-likes
2 parents ac3f5b6 + 806a538 commit 37277e8

6 files changed

+124
-1
lines changed

src/compiler/checker.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11186,7 +11186,8 @@ namespace ts {
1118611186
if (reportErrors) {
1118711187
const bestMatchingType =
1118811188
findMatchingDiscriminantType(source, target) ||
11189-
findMatchingTypeReferenceOrTypeAliasReference(source, target);
11189+
findMatchingTypeReferenceOrTypeAliasReference(source, target) ||
11190+
findBestTypeForObjectLiteral(source, target);
1119011191

1119111192
isRelatedTo(source, bestMatchingType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true);
1119211193
}
@@ -11211,6 +11212,11 @@ namespace ts {
1121111212
}
1121211213
}
1121311214

11215+
function findBestTypeForObjectLiteral(source: Type, unionTarget: UnionOrIntersectionType) {
11216+
if (getObjectFlags(source) & ObjectFlags.ObjectLiteral && forEachType(unionTarget, isArrayLikeType)) {
11217+
return find(unionTarget.types, t => !isArrayLikeType(t));
11218+
}
11219+
}
1121411220

1121511221
// Keep this up-to-date with the same logic within `getApparentTypeOfContextualType`, since they should behave similarly
1121611222
function findMatchingDiscriminantType(source: Type, target: UnionOrIntersectionType) {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts(9,5): error TS2322: Type '{ bar: { prop: number; }; }[]' is not assignable to type 'Foo[]'.
2+
Type '{ bar: { prop: number; }; }' is not assignable to type 'Foo'.
3+
Types of property 'bar' are incompatible.
4+
Type '{ prop: number; }' is not assignable to type 'Bar | Bar[]'.
5+
Type '{ prop: number; }' is not assignable to type 'Bar'.
6+
Types of property 'prop' are incompatible.
7+
Type 'number' is not assignable to type 'string'.
8+
9+
10+
==== tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts (1 errors) ====
11+
interface Foo {
12+
bar: Bar | Bar[];
13+
}
14+
15+
interface Bar {
16+
prop: string;
17+
}
18+
19+
let x: Foo[] = [
20+
~
21+
!!! error TS2322: Type '{ bar: { prop: number; }; }[]' is not assignable to type 'Foo[]'.
22+
!!! error TS2322: Type '{ bar: { prop: number; }; }' is not assignable to type 'Foo'.
23+
!!! error TS2322: Types of property 'bar' are incompatible.
24+
!!! error TS2322: Type '{ prop: number; }' is not assignable to type 'Bar | Bar[]'.
25+
!!! error TS2322: Type '{ prop: number; }' is not assignable to type 'Bar'.
26+
!!! error TS2322: Types of property 'prop' are incompatible.
27+
!!! error TS2322: Type 'number' is not assignable to type 'string'.
28+
{ bar: { prop: 100 } }
29+
]
30+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//// [objectLiteralsAgainstUnionsOfArrays01.ts]
2+
interface Foo {
3+
bar: Bar | Bar[];
4+
}
5+
6+
interface Bar {
7+
prop: string;
8+
}
9+
10+
let x: Foo[] = [
11+
{ bar: { prop: 100 } }
12+
]
13+
14+
15+
//// [objectLiteralsAgainstUnionsOfArrays01.js]
16+
var x = [
17+
{ bar: { prop: 100 } }
18+
];
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
=== tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts ===
2+
interface Foo {
3+
>Foo : Symbol(Foo, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 0, 0))
4+
5+
bar: Bar | Bar[];
6+
>bar : Symbol(Foo.bar, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 0, 15))
7+
>Bar : Symbol(Bar, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 2, 1))
8+
>Bar : Symbol(Bar, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 2, 1))
9+
}
10+
11+
interface Bar {
12+
>Bar : Symbol(Bar, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 2, 1))
13+
14+
prop: string;
15+
>prop : Symbol(Bar.prop, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 4, 15))
16+
}
17+
18+
let x: Foo[] = [
19+
>x : Symbol(x, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 8, 3))
20+
>Foo : Symbol(Foo, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 0, 0))
21+
22+
{ bar: { prop: 100 } }
23+
>bar : Symbol(bar, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 9, 3))
24+
>prop : Symbol(prop, Decl(objectLiteralsAgainstUnionsOfArrays01.ts, 9, 10))
25+
26+
]
27+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
=== tests/cases/compiler/objectLiteralsAgainstUnionsOfArrays01.ts ===
2+
interface Foo {
3+
>Foo : Foo
4+
5+
bar: Bar | Bar[];
6+
>bar : Bar | Bar[]
7+
>Bar : Bar
8+
>Bar : Bar
9+
}
10+
11+
interface Bar {
12+
>Bar : Bar
13+
14+
prop: string;
15+
>prop : string
16+
}
17+
18+
let x: Foo[] = [
19+
>x : Foo[]
20+
>Foo : Foo
21+
>[ { bar: { prop: 100 } }] : { bar: { prop: number; }; }[]
22+
23+
{ bar: { prop: 100 } }
24+
>{ bar: { prop: 100 } } : { bar: { prop: number; }; }
25+
>bar : { prop: number; }
26+
>{ prop: 100 } : { prop: number; }
27+
>prop : number
28+
>100 : 100
29+
30+
]
31+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
interface Foo {
2+
bar: Bar | Bar[];
3+
}
4+
5+
interface Bar {
6+
prop: string;
7+
}
8+
9+
let x: Foo[] = [
10+
{ bar: { prop: 100 } }
11+
]

0 commit comments

Comments
 (0)