Skip to content

Commit e7c578a

Browse files
authored
Reapply contextual type when recalculating array literals as tuples (#37071)
1 parent e71614a commit e7c578a

6 files changed

+186
-4
lines changed

Diff for: src/compiler/checker.ts

+13-4
Original file line numberDiff line numberDiff line change
@@ -14457,11 +14457,20 @@ namespace ts {
1445714457
return elaborateElementwise(generateLimitedTupleElements(node, target), source, target, relation, containingMessageChain, errorOutputContainer);
1445814458
}
1445914459
// recreate a tuple from the elements, if possible
14460-
const tupleizedType = checkArrayLiteral(node, CheckMode.Contextual, /*forceTuple*/ true);
14461-
if (isTupleLikeType(tupleizedType)) {
14462-
return elaborateElementwise(generateLimitedTupleElements(node, target), tupleizedType, target, relation, containingMessageChain, errorOutputContainer);
14460+
// Since we're re-doing the expression type, we need to reapply the contextual type
14461+
const oldContext = node.contextualType;
14462+
node.contextualType = target;
14463+
try {
14464+
const tupleizedType = checkArrayLiteral(node, CheckMode.Contextual, /*forceTuple*/ true);
14465+
node.contextualType = oldContext;
14466+
if (isTupleLikeType(tupleizedType)) {
14467+
return elaborateElementwise(generateLimitedTupleElements(node, target), tupleizedType, target, relation, containingMessageChain, errorOutputContainer);
14468+
}
14469+
return false;
14470+
}
14471+
finally {
14472+
node.contextualType = oldContext;
1446314473
}
14464-
return false;
1446514474
}
1446614475

1446714476
function *generateObjectLiteralElements(node: ObjectLiteralExpression): ElaborationIterator {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
tests/cases/compiler/errorsForCallAndAssignmentAreSimilar.ts(11,11): error TS2322: Type '"hdpvd"' is not assignable to type '"hddvd" | "bluray"'.
2+
tests/cases/compiler/errorsForCallAndAssignmentAreSimilar.ts(16,11): error TS2322: Type '"hdpvd"' is not assignable to type '"hddvd" | "bluray"'.
3+
4+
5+
==== tests/cases/compiler/errorsForCallAndAssignmentAreSimilar.ts (2 errors) ====
6+
function minimalExample1() {
7+
type Disc =
8+
| { kind: "hddvd" }
9+
| { kind: "bluray" }
10+
11+
function foo(x: Disc[]) {
12+
}
13+
14+
foo([
15+
{ kind: "bluray", },
16+
{ kind: "hdpvd", }
17+
~~~~
18+
!!! error TS2322: Type '"hdpvd"' is not assignable to type '"hddvd" | "bluray"'.
19+
!!! related TS6500 tests/cases/compiler/errorsForCallAndAssignmentAreSimilar.ts:3:13: The expected type comes from property 'kind' which is declared here on type 'Disc'
20+
]);
21+
22+
const ds: Disc[] = [
23+
{ kind: "bluray", },
24+
{ kind: "hdpvd", }
25+
~~~~
26+
!!! error TS2322: Type '"hdpvd"' is not assignable to type '"hddvd" | "bluray"'.
27+
!!! related TS6500 tests/cases/compiler/errorsForCallAndAssignmentAreSimilar.ts:3:13: The expected type comes from property 'kind' which is declared here on type 'Disc'
28+
];
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//// [errorsForCallAndAssignmentAreSimilar.ts]
2+
function minimalExample1() {
3+
type Disc =
4+
| { kind: "hddvd" }
5+
| { kind: "bluray" }
6+
7+
function foo(x: Disc[]) {
8+
}
9+
10+
foo([
11+
{ kind: "bluray", },
12+
{ kind: "hdpvd", }
13+
]);
14+
15+
const ds: Disc[] = [
16+
{ kind: "bluray", },
17+
{ kind: "hdpvd", }
18+
];
19+
}
20+
21+
//// [errorsForCallAndAssignmentAreSimilar.js]
22+
function minimalExample1() {
23+
function foo(x) {
24+
}
25+
foo([
26+
{ kind: "bluray" },
27+
{ kind: "hdpvd" }
28+
]);
29+
var ds = [
30+
{ kind: "bluray" },
31+
{ kind: "hdpvd" }
32+
];
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
=== tests/cases/compiler/errorsForCallAndAssignmentAreSimilar.ts ===
2+
function minimalExample1() {
3+
>minimalExample1 : Symbol(minimalExample1, Decl(errorsForCallAndAssignmentAreSimilar.ts, 0, 0))
4+
5+
type Disc =
6+
>Disc : Symbol(Disc, Decl(errorsForCallAndAssignmentAreSimilar.ts, 0, 28))
7+
8+
| { kind: "hddvd" }
9+
>kind : Symbol(kind, Decl(errorsForCallAndAssignmentAreSimilar.ts, 2, 11))
10+
11+
| { kind: "bluray" }
12+
>kind : Symbol(kind, Decl(errorsForCallAndAssignmentAreSimilar.ts, 3, 11))
13+
14+
function foo(x: Disc[]) {
15+
>foo : Symbol(foo, Decl(errorsForCallAndAssignmentAreSimilar.ts, 3, 28))
16+
>x : Symbol(x, Decl(errorsForCallAndAssignmentAreSimilar.ts, 5, 17))
17+
>Disc : Symbol(Disc, Decl(errorsForCallAndAssignmentAreSimilar.ts, 0, 28))
18+
}
19+
20+
foo([
21+
>foo : Symbol(foo, Decl(errorsForCallAndAssignmentAreSimilar.ts, 3, 28))
22+
23+
{ kind: "bluray", },
24+
>kind : Symbol(kind, Decl(errorsForCallAndAssignmentAreSimilar.ts, 9, 9))
25+
26+
{ kind: "hdpvd", }
27+
>kind : Symbol(kind, Decl(errorsForCallAndAssignmentAreSimilar.ts, 10, 9))
28+
29+
]);
30+
31+
const ds: Disc[] = [
32+
>ds : Symbol(ds, Decl(errorsForCallAndAssignmentAreSimilar.ts, 13, 9))
33+
>Disc : Symbol(Disc, Decl(errorsForCallAndAssignmentAreSimilar.ts, 0, 28))
34+
35+
{ kind: "bluray", },
36+
>kind : Symbol(kind, Decl(errorsForCallAndAssignmentAreSimilar.ts, 14, 9))
37+
38+
{ kind: "hdpvd", }
39+
>kind : Symbol(kind, Decl(errorsForCallAndAssignmentAreSimilar.ts, 15, 9))
40+
41+
];
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
=== tests/cases/compiler/errorsForCallAndAssignmentAreSimilar.ts ===
2+
function minimalExample1() {
3+
>minimalExample1 : () => void
4+
5+
type Disc =
6+
>Disc : { kind: "hddvd"; } | { kind: "bluray"; }
7+
8+
| { kind: "hddvd" }
9+
>kind : "hddvd"
10+
11+
| { kind: "bluray" }
12+
>kind : "bluray"
13+
14+
function foo(x: Disc[]) {
15+
>foo : (x: ({ kind: "hddvd"; } | { kind: "bluray"; })[]) => void
16+
>x : ({ kind: "hddvd"; } | { kind: "bluray"; })[]
17+
}
18+
19+
foo([
20+
>foo([ { kind: "bluray", }, { kind: "hdpvd", } ]) : void
21+
>foo : (x: ({ kind: "hddvd"; } | { kind: "bluray"; })[]) => void
22+
>[ { kind: "bluray", }, { kind: "hdpvd", } ] : ({ kind: "bluray"; } | { kind: "hdpvd"; })[]
23+
24+
{ kind: "bluray", },
25+
>{ kind: "bluray", } : { kind: "bluray"; }
26+
>kind : "bluray"
27+
>"bluray" : "bluray"
28+
29+
{ kind: "hdpvd", }
30+
>{ kind: "hdpvd", } : { kind: "hdpvd"; }
31+
>kind : "hdpvd"
32+
>"hdpvd" : "hdpvd"
33+
34+
]);
35+
36+
const ds: Disc[] = [
37+
>ds : ({ kind: "hddvd"; } | { kind: "bluray"; })[]
38+
>[ { kind: "bluray", }, { kind: "hdpvd", } ] : ({ kind: "bluray"; } | { kind: "hdpvd"; })[]
39+
40+
{ kind: "bluray", },
41+
>{ kind: "bluray", } : { kind: "bluray"; }
42+
>kind : "bluray"
43+
>"bluray" : "bluray"
44+
45+
{ kind: "hdpvd", }
46+
>{ kind: "hdpvd", } : { kind: "hdpvd"; }
47+
>kind : "hdpvd"
48+
>"hdpvd" : "hdpvd"
49+
50+
];
51+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
function minimalExample1() {
2+
type Disc =
3+
| { kind: "hddvd" }
4+
| { kind: "bluray" }
5+
6+
function foo(x: Disc[]) {
7+
}
8+
9+
foo([
10+
{ kind: "bluray", },
11+
{ kind: "hdpvd", }
12+
]);
13+
14+
const ds: Disc[] = [
15+
{ kind: "bluray", },
16+
{ kind: "hdpvd", }
17+
];
18+
}

0 commit comments

Comments
 (0)