Skip to content

Commit 9558c21

Browse files
committed
Defer checking:this param in object literal method
This is completely ad-hoc, but it allows you to write `this: typeof o` in an object literal and get the entire type.
1 parent 99743df commit 9558c21

File tree

5 files changed

+171
-14
lines changed

5 files changed

+171
-14
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15748,7 +15748,18 @@ namespace ts {
1574815748

1574915749
checkTypeParameters(node.typeParameters);
1575015750

15751-
forEach(node.parameters, checkParameter);
15751+
const isObjectLiteralMethodWithThis = isObjectLiteralMethod(node) &&
15752+
node.parameters &&
15753+
node.parameters.length &&
15754+
parameterIsThisKeyword(node.parameters[0]);
15755+
if (isObjectLiteralMethodWithThis) {
15756+
// defer checking on first one
15757+
checkNodeDeferred(node.parameters[0]); // .. this will surely work ..
15758+
forEach(node.parameters.slice(1), checkParameter);
15759+
}
15760+
else {
15761+
forEach(node.parameters, checkParameter);
15762+
}
1575215763

1575315764
if (node.type) {
1575415765
checkSourceElement(node.type);
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//// [recursion.ts]
2+
let o = {
3+
p: 12,
4+
m(this: typeof o) {
5+
let x = this.m(); // x: number
6+
let y = this.p; // y: number
7+
return this.p;
8+
},
9+
m2() {
10+
return this.m() // this: any since it has no annotation
11+
}
12+
}
13+
14+
let x = o.m() // x: number
15+
let y = o.m2() // y: any
16+
let p = o.p // p: number
17+
18+
19+
//// [recursion.js]
20+
var o = {
21+
p: 12,
22+
m: function () {
23+
var x = this.m(); // x: number
24+
var y = this.p; // y: number
25+
return this.p;
26+
},
27+
m2: function () {
28+
return this.m(); // this: any since it has no annotation
29+
}
30+
};
31+
var x = o.m(); // x: number
32+
var y = o.m2(); // y: any
33+
var p = o.p; // p: number
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
=== tests/cases/compiler/recursion.ts ===
2+
let o = {
3+
>o : Symbol(o, Decl(recursion.ts, 0, 3))
4+
5+
p: 12,
6+
>p : Symbol(p, Decl(recursion.ts, 0, 9))
7+
8+
m(this: typeof o) {
9+
>m : Symbol(m, Decl(recursion.ts, 1, 10))
10+
>this : Symbol(this, Decl(recursion.ts, 2, 6))
11+
>o : Symbol(o, Decl(recursion.ts, 0, 3))
12+
13+
let x = this.m(); // x: number
14+
>x : Symbol(x, Decl(recursion.ts, 3, 11))
15+
>this.m : Symbol(m, Decl(recursion.ts, 1, 10))
16+
>this : Symbol(this, Decl(recursion.ts, 2, 6))
17+
>m : Symbol(m, Decl(recursion.ts, 1, 10))
18+
19+
let y = this.p; // y: number
20+
>y : Symbol(y, Decl(recursion.ts, 4, 11))
21+
>this.p : Symbol(p, Decl(recursion.ts, 0, 9))
22+
>this : Symbol(this, Decl(recursion.ts, 2, 6))
23+
>p : Symbol(p, Decl(recursion.ts, 0, 9))
24+
25+
return this.p;
26+
>this.p : Symbol(p, Decl(recursion.ts, 0, 9))
27+
>this : Symbol(this, Decl(recursion.ts, 2, 6))
28+
>p : Symbol(p, Decl(recursion.ts, 0, 9))
29+
30+
},
31+
m2() {
32+
>m2 : Symbol(m2, Decl(recursion.ts, 6, 6))
33+
34+
return this.m() // this: any since it has no annotation
35+
}
36+
}
37+
38+
let x = o.m() // x: number
39+
>x : Symbol(x, Decl(recursion.ts, 12, 3))
40+
>o.m : Symbol(m, Decl(recursion.ts, 1, 10))
41+
>o : Symbol(o, Decl(recursion.ts, 0, 3))
42+
>m : Symbol(m, Decl(recursion.ts, 1, 10))
43+
44+
let y = o.m2() // y: any
45+
>y : Symbol(y, Decl(recursion.ts, 13, 3))
46+
>o.m2 : Symbol(m2, Decl(recursion.ts, 6, 6))
47+
>o : Symbol(o, Decl(recursion.ts, 0, 3))
48+
>m2 : Symbol(m2, Decl(recursion.ts, 6, 6))
49+
50+
let p = o.p // p: number
51+
>p : Symbol(p, Decl(recursion.ts, 14, 3))
52+
>o.p : Symbol(p, Decl(recursion.ts, 0, 9))
53+
>o : Symbol(o, Decl(recursion.ts, 0, 3))
54+
>p : Symbol(p, Decl(recursion.ts, 0, 9))
55+
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
=== tests/cases/compiler/recursion.ts ===
2+
let o = {
3+
>o : { p: number; m(this: any): number; m2(): any; }
4+
>{ p: 12, m(this: typeof o) { let x = this.m(); // x: number let y = this.p; // y: number return this.p; }, m2() { return this.m() // this: any since it has no annotation }} : { p: number; m(this: any): number; m2(): any; }
5+
6+
p: 12,
7+
>p : number
8+
>12 : 12
9+
10+
m(this: typeof o) {
11+
>m : (this: { p: number; m(this: any): number; m2(): any; }) => number
12+
>this : { p: number; m(this: any): number; m2(): any; }
13+
>o : { p: number; m(this: any): number; m2(): any; }
14+
15+
let x = this.m(); // x: number
16+
>x : number
17+
>this.m() : number
18+
>this.m : (this: { p: number; m(this: any): number; m2(): any; }) => number
19+
>this : { p: number; m(this: any): number; m2(): any; }
20+
>m : (this: { p: number; m(this: any): number; m2(): any; }) => number
21+
22+
let y = this.p; // y: number
23+
>y : number
24+
>this.p : number
25+
>this : { p: number; m(this: any): number; m2(): any; }
26+
>p : number
27+
28+
return this.p;
29+
>this.p : number
30+
>this : { p: number; m(this: any): number; m2(): any; }
31+
>p : number
32+
33+
},
34+
m2() {
35+
>m2 : () => any
36+
37+
return this.m() // this: any since it has no annotation
38+
>this.m() : any
39+
>this.m : any
40+
>this : any
41+
>m : any
42+
}
43+
}
44+
45+
let x = o.m() // x: number
46+
>x : number
47+
>o.m() : number
48+
>o.m : (this: { p: number; m(this: any): number; m2(): any; }) => number
49+
>o : { p: number; m(this: any): number; m2(): any; }
50+
>m : (this: { p: number; m(this: any): number; m2(): any; }) => number
51+
52+
let y = o.m2() // y: any
53+
>y : any
54+
>o.m2() : any
55+
>o.m2 : () => any
56+
>o : { p: number; m(this: any): number; m2(): any; }
57+
>m2 : () => any
58+
59+
let p = o.p // p: number
60+
>p : number
61+
>o.p : number
62+
>o : { p: number; m(this: any): number; m2(): any; }
63+
>p : number
64+

tests/cases/compiler/recursion.ts

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,15 @@
11
let o = {
22
p: 12,
33
m(this: typeof o) {
4+
let x = this.m(); // x: number
5+
let y = this.p; // y: number
46
return this.p;
5-
}
6-
}
7-
let o2 = {
8-
p: 12,
9-
m() {
10-
let x: typeof o2;
11-
let y = this.p // nope, any
12-
return x.p // ok???
13-
}
7+
},
148
m2() {
15-
return this.m() // still any!
9+
return this.m() // this: any since it has no annotation
1610
}
1711
}
1812

19-
let x = o2.m()
20-
let y = o2.m2()
21-
let p = o2.p
13+
let x = o.m() // x: number
14+
let y = o.m2() // y: any
15+
let p = o.p // p: number

0 commit comments

Comments
 (0)