Skip to content

Commit 3f6aa3f

Browse files
authored
Fix 10076: Fix Tuple Destructing with "this" (#10208)
* Call checkExpression eventhough there is no appropriate type from destructuring of array * Add tests and baselines
1 parent 30e95df commit 3f6aa3f

7 files changed

+88
-3
lines changed

src/compiler/checker.ts

Lines changed: 11 additions & 3 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -4457,9 +4457,14 @@ namespace ts {
4457
return property;
4457
return property;
4458
}
4458
}
4459

4459

4460-
// Return the symbol for the property with the given name in the given type. Creates synthetic union properties when
4460+
/**
4461-
// necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from
4461+
* Return the symbol for the property with the given name in the given type. Creates synthetic union properties when
4462-
// Object and Function as appropriate.
4462+
* necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from
4463+
* Object and Function as appropriate.
4464+
*
4465+
* @param type a type to look up property from
4466+
* @param name a name of property to look up in a given type
4467+
*/
4463
function getPropertyOfType(type: Type, name: string): Symbol {
4468
function getPropertyOfType(type: Type, name: string): Symbol {
4464
type = getApparentType(type);
4469
type = getApparentType(type);
4465
if (type.flags & TypeFlags.ObjectType) {
4470
if (type.flags & TypeFlags.ObjectType) {
@@ -12932,6 +12937,9 @@ namespace ts {
12932
return checkDestructuringAssignment(element, type, contextualMapper);
12937
return checkDestructuringAssignment(element, type, contextualMapper);
12933
}
12938
}
12934
else {
12939
else {
12940+
// We still need to check element expression here because we may need to set appropriate flag on the expression
12941+
// such as NodeCheckFlags.LexicalThis on "this"expression.
12942+
checkExpression(element);
12935
if (isTupleType(sourceType)) {
12943
if (isTupleType(sourceType)) {
12936
error(element, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), (<TupleType>sourceType).elementTypes.length, elements.length);
12944
error(element, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), (<TupleType>sourceType).elementTypes.length, elements.length);
12937
}
12945
}
Lines changed: 13 additions & 0 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts(3,17): error TS2493: Tuple type '[any]' with length '1' cannot be assigned to tuple with length '3'.
2+
tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts(3,29): error TS2493: Tuple type '[any]' with length '1' cannot be assigned to tuple with length '3'.
3+
4+
5+
==== tests/cases/compiler/emitCapturingThisInTupleDestructuring1.ts (2 errors) ====
6+
declare function wrapper(x: any);
7+
wrapper((array: [any]) => {
8+
[this.test, this.test1, this.test2] = array; // even though there is a compiler error, we should still emit lexical capture for "this"
9+
~~~~~~~~~~
10+
!!! error TS2493: Tuple type '[any]' with length '1' cannot be assigned to tuple with length '3'.
11+
~~~~~~~~~~
12+
!!! error TS2493: Tuple type '[any]' with length '1' cannot be assigned to tuple with length '3'.
13+
});
Lines changed: 11 additions & 0 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//// [emitCapturingThisInTupleDestructuring1.ts]
2+
declare function wrapper(x: any);
3+
wrapper((array: [any]) => {
4+
[this.test, this.test1, this.test2] = array; // even though there is a compiler error, we should still emit lexical capture for "this"
5+
});
6+
7+
//// [emitCapturingThisInTupleDestructuring1.js]
8+
var _this = this;
9+
wrapper(function (array) {
10+
_this.test = array[0], _this.test1 = array[1], _this.test2 = array[2]; // even though there is a compiler error, we should still emit lexical capture for "this"
11+
});
Lines changed: 16 additions & 0 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
tests/cases/compiler/emitCapturingThisInTupleDestructuring2.ts(8,39): error TS2493: Tuple type '[number, number]' with length '2' cannot be assigned to tuple with length '3'.
2+
3+
4+
==== tests/cases/compiler/emitCapturingThisInTupleDestructuring2.ts (1 errors) ====
5+
var array1: [number, number] = [1, 2];
6+
7+
class B {
8+
test: number;
9+
test1: any;
10+
test2: any;
11+
method() {
12+
() => [this.test, this.test1, this.test2] = array1; // even though there is a compiler error, we should still emit lexical capture for "this"
13+
~~~~~~~~~~
14+
!!! error TS2493: Tuple type '[number, number]' with length '2' cannot be assigned to tuple with length '3'.
15+
}
16+
}
Lines changed: 23 additions & 0 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//// [emitCapturingThisInTupleDestructuring2.ts]
2+
var array1: [number, number] = [1, 2];
3+
4+
class B {
5+
test: number;
6+
test1: any;
7+
test2: any;
8+
method() {
9+
() => [this.test, this.test1, this.test2] = array1; // even though there is a compiler error, we should still emit lexical capture for "this"
10+
}
11+
}
12+
13+
//// [emitCapturingThisInTupleDestructuring2.js]
14+
var array1 = [1, 2];
15+
var B = (function () {
16+
function B() {
17+
}
18+
B.prototype.method = function () {
19+
var _this = this;
20+
(function () { return (_this.test = array1[0], _this.test1 = array1[1], _this.test2 = array1[2], array1); }); // even though there is a compiler error, we should still emit lexical capture for "this"
21+
};
22+
return B;
23+
}());
Lines changed: 4 additions & 0 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
declare function wrapper(x: any);
2+
wrapper((array: [any]) => {
3+
[this.test, this.test1, this.test2] = array; // even though there is a compiler error, we should still emit lexical capture for "this"
4+
});
Lines changed: 10 additions & 0 deletions
Original file line numberOriginal file lineDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
var array1: [number, number] = [1, 2];
2+
3+
class B {
4+
test: number;
5+
test1: any;
6+
test2: any;
7+
method() {
8+
() => [this.test, this.test1, this.test2] = array1; // even though there is a compiler error, we should still emit lexical capture for "this"
9+
}
10+
}

0 commit comments

Comments
 (0)