Skip to content

Commit 334b8ea

Browse files
Bind assignments to 'this' within static blocks in JS files (#46472)
* Add failing test case. * Handle 'this' assignments on class static blocks in JavaScript. * Accepted baselines.
1 parent de1ac81 commit 334b8ea

6 files changed

+234
-0
lines changed

src/compiler/binder.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2947,6 +2947,7 @@ namespace ts {
29472947
case SyntaxKind.MethodDeclaration:
29482948
case SyntaxKind.GetAccessor:
29492949
case SyntaxKind.SetAccessor:
2950+
case SyntaxKind.ClassStaticBlockDeclaration:
29502951
// this.foo assignment in a JavaScript class
29512952
// Bind this property to the containing class
29522953
const containingClass = thisContainer.parent;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/src/a.js(10,7): error TS2417: Class static side 'typeof ElementsArray' incorrectly extends base class static side '{ isArray(arg: any): arg is any[]; readonly prototype: any[]; }'.
2+
Types of property 'isArray' are incompatible.
3+
Type '(arg: any) => boolean' is not assignable to type '(arg: any) => arg is any[]'.
4+
Signature '(arg: any): boolean' must be a type predicate.
5+
6+
7+
==== /src/a.js (1 errors) ====
8+
class Thing {
9+
static {
10+
this.doSomething = () => {};
11+
}
12+
}
13+
14+
Thing.doSomething();
15+
16+
// GH#46468
17+
class ElementsArray extends Array {
18+
~~~~~~~~~~~~~
19+
!!! error TS2417: Class static side 'typeof ElementsArray' incorrectly extends base class static side '{ isArray(arg: any): arg is any[]; readonly prototype: any[]; }'.
20+
!!! error TS2417: Types of property 'isArray' are incompatible.
21+
!!! error TS2417: Type '(arg: any) => boolean' is not assignable to type '(arg: any) => arg is any[]'.
22+
!!! error TS2417: Signature '(arg: any): boolean' must be a type predicate.
23+
static {
24+
const superisArray = super.isArray;
25+
const customIsArray = (arg)=> superisArray(arg);
26+
this.isArray = customIsArray;
27+
}
28+
}
29+
30+
ElementsArray.isArray(new ElementsArray());
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//// [a.js]
2+
class Thing {
3+
static {
4+
this.doSomething = () => {};
5+
}
6+
}
7+
8+
Thing.doSomething();
9+
10+
// GH#46468
11+
class ElementsArray extends Array {
12+
static {
13+
const superisArray = super.isArray;
14+
const customIsArray = (arg)=> superisArray(arg);
15+
this.isArray = customIsArray;
16+
}
17+
}
18+
19+
ElementsArray.isArray(new ElementsArray());
20+
21+
//// [a.js]
22+
var __extends = (this && this.__extends) || (function () {
23+
var extendStatics = function (d, b) {
24+
extendStatics = Object.setPrototypeOf ||
25+
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
26+
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
27+
return extendStatics(d, b);
28+
};
29+
return function (d, b) {
30+
if (typeof b !== "function" && b !== null)
31+
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
32+
extendStatics(d, b);
33+
function __() { this.constructor = d; }
34+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
35+
};
36+
})();
37+
var _a, _b;
38+
var _this = this;
39+
var Thing = /** @class */ (function () {
40+
function Thing() {
41+
}
42+
return Thing;
43+
}());
44+
_a = Thing;
45+
(function () {
46+
_a.doSomething = function () { };
47+
})();
48+
Thing.doSomething();
49+
// GH#46468
50+
var ElementsArray = /** @class */ (function (_super) {
51+
__extends(ElementsArray, _super);
52+
function ElementsArray() {
53+
return _super !== null && _super.apply(this, arguments) || this;
54+
}
55+
return ElementsArray;
56+
}(Array));
57+
_b = ElementsArray;
58+
(function () {
59+
var superisArray = _super.isArray;
60+
var customIsArray = function (arg) { return superisArray(arg); };
61+
_b.isArray = customIsArray;
62+
})();
63+
ElementsArray.isArray(new ElementsArray());
64+
65+
66+
//// [a.d.ts]
67+
declare class Thing {
68+
}
69+
declare class ElementsArray extends Array<any> {
70+
constructor(arrayLength?: number);
71+
constructor(arrayLength: number);
72+
constructor(...items: any[]);
73+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
=== /src/a.js ===
2+
class Thing {
3+
>Thing : Symbol(Thing, Decl(a.js, 0, 0))
4+
5+
static {
6+
this.doSomething = () => {};
7+
>this.doSomething : Symbol(Thing.doSomething, Decl(a.js, 1, 12))
8+
>this : Symbol(Thing, Decl(a.js, 0, 0))
9+
>doSomething : Symbol(Thing.doSomething, Decl(a.js, 1, 12))
10+
}
11+
}
12+
13+
Thing.doSomething();
14+
>Thing.doSomething : Symbol(Thing.doSomething, Decl(a.js, 1, 12))
15+
>Thing : Symbol(Thing, Decl(a.js, 0, 0))
16+
>doSomething : Symbol(Thing.doSomething, Decl(a.js, 1, 12))
17+
18+
// GH#46468
19+
class ElementsArray extends Array {
20+
>ElementsArray : Symbol(ElementsArray, Decl(a.js, 6, 20))
21+
>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
22+
23+
static {
24+
const superisArray = super.isArray;
25+
>superisArray : Symbol(superisArray, Decl(a.js, 11, 13))
26+
>super.isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
27+
>super : Symbol(ArrayConstructor, Decl(lib.es5.d.ts, --, --))
28+
>isArray : Symbol(ArrayConstructor.isArray, Decl(lib.es5.d.ts, --, --))
29+
30+
const customIsArray = (arg)=> superisArray(arg);
31+
>customIsArray : Symbol(customIsArray, Decl(a.js, 12, 13))
32+
>arg : Symbol(arg, Decl(a.js, 12, 31))
33+
>superisArray : Symbol(superisArray, Decl(a.js, 11, 13))
34+
>arg : Symbol(arg, Decl(a.js, 12, 31))
35+
36+
this.isArray = customIsArray;
37+
>this.isArray : Symbol(ElementsArray.isArray, Decl(a.js, 12, 56))
38+
>this : Symbol(ElementsArray, Decl(a.js, 6, 20))
39+
>isArray : Symbol(ElementsArray.isArray, Decl(a.js, 12, 56))
40+
>customIsArray : Symbol(customIsArray, Decl(a.js, 12, 13))
41+
}
42+
}
43+
44+
ElementsArray.isArray(new ElementsArray());
45+
>ElementsArray.isArray : Symbol(ElementsArray.isArray, Decl(a.js, 12, 56))
46+
>ElementsArray : Symbol(ElementsArray, Decl(a.js, 6, 20))
47+
>isArray : Symbol(ElementsArray.isArray, Decl(a.js, 12, 56))
48+
>ElementsArray : Symbol(ElementsArray, Decl(a.js, 6, 20))
49+
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
=== /src/a.js ===
2+
class Thing {
3+
>Thing : Thing
4+
5+
static {
6+
this.doSomething = () => {};
7+
>this.doSomething = () => {} : () => void
8+
>this.doSomething : () => void
9+
>this : typeof Thing
10+
>doSomething : () => void
11+
>() => {} : () => void
12+
}
13+
}
14+
15+
Thing.doSomething();
16+
>Thing.doSomething() : void
17+
>Thing.doSomething : () => void
18+
>Thing : typeof Thing
19+
>doSomething : () => void
20+
21+
// GH#46468
22+
class ElementsArray extends Array {
23+
>ElementsArray : ElementsArray
24+
>Array : any[]
25+
26+
static {
27+
const superisArray = super.isArray;
28+
>superisArray : (arg: any) => arg is any[]
29+
>super.isArray : (arg: any) => arg is any[]
30+
>super : ArrayConstructor
31+
>isArray : (arg: any) => arg is any[]
32+
33+
const customIsArray = (arg)=> superisArray(arg);
34+
>customIsArray : (arg: any) => boolean
35+
>(arg)=> superisArray(arg) : (arg: any) => boolean
36+
>arg : any
37+
>superisArray(arg) : boolean
38+
>superisArray : (arg: any) => arg is any[]
39+
>arg : any
40+
41+
this.isArray = customIsArray;
42+
>this.isArray = customIsArray : (arg: any) => boolean
43+
>this.isArray : (arg: any) => boolean
44+
>this : typeof ElementsArray
45+
>isArray : (arg: any) => boolean
46+
>customIsArray : (arg: any) => boolean
47+
}
48+
}
49+
50+
ElementsArray.isArray(new ElementsArray());
51+
>ElementsArray.isArray(new ElementsArray()) : boolean
52+
>ElementsArray.isArray : (arg: any) => boolean
53+
>ElementsArray : typeof ElementsArray
54+
>isArray : (arg: any) => boolean
55+
>new ElementsArray() : ElementsArray
56+
>ElementsArray : typeof ElementsArray
57+
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// @allowJs: true
2+
// @checkJs: true
3+
// @declaration: true
4+
// @outDir: /out/
5+
// @filename: /src/a.js
6+
7+
class Thing {
8+
static {
9+
this.doSomething = () => {};
10+
}
11+
}
12+
13+
Thing.doSomething();
14+
15+
// GH#46468
16+
class ElementsArray extends Array {
17+
static {
18+
const superisArray = super.isArray;
19+
const customIsArray = (arg)=> superisArray(arg);
20+
this.isArray = customIsArray;
21+
}
22+
}
23+
24+
ElementsArray.isArray(new ElementsArray());

0 commit comments

Comments
 (0)