Skip to content

Commit 70d14f3

Browse files
authored
fix(52594): this incorrectly applies in TS files in typeToString (#52610)
1 parent 0bf9991 commit 70d14f3

8 files changed

+406
-3
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7307,7 +7307,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
73077307
if (signature.thisParameter) {
73087308
return symbolToParameterDeclaration(signature.thisParameter, context);
73097309
}
7310-
if (signature.declaration) {
7310+
if (signature.declaration && isInJSFile(signature.declaration)) {
73117311
const thisTag = getJSDocThisTag(signature.declaration);
73127312
if (thisTag && thisTag.typeExpression) {
73137313
return factory.createParameterDeclaration(
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
=== /a.ts ===
2+
// /** @this {number} */
3+
// function f() {
4+
// ^
5+
// | ----------------------------------------------------------------------
6+
// | function f(): void
7+
// | @this
8+
// | ----------------------------------------------------------------------
9+
// this
10+
// }
11+
12+
[
13+
{
14+
"marker": {
15+
"fileName": "/a.ts",
16+
"position": 32,
17+
"name": ""
18+
},
19+
"item": {
20+
"kind": "function",
21+
"kindModifiers": "",
22+
"textSpan": {
23+
"start": 31,
24+
"length": 1
25+
},
26+
"displayParts": [
27+
{
28+
"text": "function",
29+
"kind": "keyword"
30+
},
31+
{
32+
"text": " ",
33+
"kind": "space"
34+
},
35+
{
36+
"text": "f",
37+
"kind": "functionName"
38+
},
39+
{
40+
"text": "(",
41+
"kind": "punctuation"
42+
},
43+
{
44+
"text": ")",
45+
"kind": "punctuation"
46+
},
47+
{
48+
"text": ":",
49+
"kind": "punctuation"
50+
},
51+
{
52+
"text": " ",
53+
"kind": "space"
54+
},
55+
{
56+
"text": "void",
57+
"kind": "keyword"
58+
}
59+
],
60+
"documentation": [],
61+
"tags": [
62+
{
63+
"name": "this"
64+
}
65+
]
66+
}
67+
}
68+
]

tests/baselines/reference/thisInFunctionCall.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ class Test {
8484

8585
/** @this {Test} */
8686
function (d) {
87-
>function (d) { console.log(d === this.data.length) } : (this: Test, d: number) => void
87+
>function (d) { console.log(d === this.data.length) } : (d: number) => void
8888
>d : number
8989

9090
console.log(d === this.data.length)
@@ -117,7 +117,7 @@ class Test {
117117

118118
/** @this {Test} */
119119
function (d) {
120-
>function (d) { return d === this.data.length } : (this: Test, d: number) => boolean
120+
>function (d) { return d === this.data.length } : (d: number) => boolean
121121
>d : number
122122

123123
return d === this.data.length
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/a.js(9,26): error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
2+
/a.js(15,31): error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
3+
4+
5+
==== /a.js (2 errors) ====
6+
class Test {
7+
constructor() {
8+
/** @type {number[]} */
9+
this.data = [1, 2, 3];
10+
}
11+
12+
finderRaw() {
13+
this.data.find(function (d) {
14+
return d === this.data.length
15+
~~~~
16+
!!! error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
17+
!!! related TS2738 /a.js:8:24: An outer value of 'this' is shadowed by this container.
18+
})
19+
}
20+
21+
forEacherRaw() {
22+
this.data.forEach(function (d) {
23+
console.log(d === this.data.length)
24+
~~~~
25+
!!! error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
26+
!!! related TS2738 /a.js:14:27: An outer value of 'this' is shadowed by this container.
27+
})
28+
}
29+
30+
forEacher() {
31+
this.data.forEach(
32+
/** @this {Test} */
33+
function (d) {
34+
console.log(d === this.data.length)
35+
}, this)
36+
}
37+
38+
finder() {
39+
this.data.find(
40+
/** @this {Test} */
41+
function (d) {
42+
return d === this.data.length
43+
}, this)
44+
}
45+
}
46+
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
=== /a.js ===
2+
class Test {
3+
>Test : Symbol(Test, Decl(a.js, 0, 0))
4+
5+
constructor() {
6+
/** @type {number[]} */
7+
this.data = [1, 2, 3];
8+
>this.data : Symbol(Test.data, Decl(a.js, 1, 19))
9+
>this : Symbol(Test, Decl(a.js, 0, 0))
10+
>data : Symbol(Test.data, Decl(a.js, 1, 19))
11+
}
12+
13+
finderRaw() {
14+
>finderRaw : Symbol(Test.finderRaw, Decl(a.js, 4, 5))
15+
16+
this.data.find(function (d) {
17+
>this.data.find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
18+
>this.data : Symbol(Test.data, Decl(a.js, 1, 19))
19+
>this : Symbol(Test, Decl(a.js, 0, 0))
20+
>data : Symbol(Test.data, Decl(a.js, 1, 19))
21+
>find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
22+
>d : Symbol(d, Decl(a.js, 7, 33))
23+
24+
return d === this.data.length
25+
>d : Symbol(d, Decl(a.js, 7, 33))
26+
27+
})
28+
}
29+
30+
forEacherRaw() {
31+
>forEacherRaw : Symbol(Test.forEacherRaw, Decl(a.js, 10, 5))
32+
33+
this.data.forEach(function (d) {
34+
>this.data.forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --))
35+
>this.data : Symbol(Test.data, Decl(a.js, 1, 19))
36+
>this : Symbol(Test, Decl(a.js, 0, 0))
37+
>data : Symbol(Test.data, Decl(a.js, 1, 19))
38+
>forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --))
39+
>d : Symbol(d, Decl(a.js, 13, 36))
40+
41+
console.log(d === this.data.length)
42+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
43+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
44+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
45+
>d : Symbol(d, Decl(a.js, 13, 36))
46+
47+
})
48+
}
49+
50+
forEacher() {
51+
>forEacher : Symbol(Test.forEacher, Decl(a.js, 16, 5))
52+
53+
this.data.forEach(
54+
>this.data.forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --))
55+
>this.data : Symbol(Test.data, Decl(a.js, 1, 19))
56+
>this : Symbol(Test, Decl(a.js, 0, 0))
57+
>data : Symbol(Test.data, Decl(a.js, 1, 19))
58+
>forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --))
59+
60+
/** @this {Test} */
61+
function (d) {
62+
>d : Symbol(d, Decl(a.js, 21, 18))
63+
64+
console.log(d === this.data.length)
65+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
66+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
67+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
68+
>d : Symbol(d, Decl(a.js, 21, 18))
69+
>this.data.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
70+
>this.data : Symbol(Test.data, Decl(a.js, 1, 19))
71+
>this : Symbol(this)
72+
>data : Symbol(Test.data, Decl(a.js, 1, 19))
73+
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
74+
75+
}, this)
76+
>this : Symbol(Test, Decl(a.js, 0, 0))
77+
}
78+
79+
finder() {
80+
>finder : Symbol(Test.finder, Decl(a.js, 24, 5))
81+
82+
this.data.find(
83+
>this.data.find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
84+
>this.data : Symbol(Test.data, Decl(a.js, 1, 19))
85+
>this : Symbol(Test, Decl(a.js, 0, 0))
86+
>data : Symbol(Test.data, Decl(a.js, 1, 19))
87+
>find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
88+
89+
/** @this {Test} */
90+
function (d) {
91+
>d : Symbol(d, Decl(a.js, 29, 18))
92+
93+
return d === this.data.length
94+
>d : Symbol(d, Decl(a.js, 29, 18))
95+
>this.data.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
96+
>this.data : Symbol(Test.data, Decl(a.js, 1, 19))
97+
>this : Symbol(this)
98+
>data : Symbol(Test.data, Decl(a.js, 1, 19))
99+
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
100+
101+
}, this)
102+
>this : Symbol(Test, Decl(a.js, 0, 0))
103+
}
104+
}
105+
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
=== /a.js ===
2+
class Test {
3+
>Test : Test
4+
5+
constructor() {
6+
/** @type {number[]} */
7+
this.data = [1, 2, 3];
8+
>this.data = [1, 2, 3] : number[]
9+
>this.data : number[]
10+
>this : this
11+
>data : number[]
12+
>[1, 2, 3] : number[]
13+
>1 : 1
14+
>2 : 2
15+
>3 : 3
16+
}
17+
18+
finderRaw() {
19+
>finderRaw : () => void
20+
21+
this.data.find(function (d) {
22+
>this.data.find(function (d) { return d === this.data.length }) : number
23+
>this.data.find : { <S extends number>(predicate: (value: number, index: number, obj: number[]) => value is S, thisArg?: any): S; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }
24+
>this.data : number[]
25+
>this : this
26+
>data : number[]
27+
>find : { <S extends number>(predicate: (value: number, index: number, obj: number[]) => value is S, thisArg?: any): S; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }
28+
>function (d) { return d === this.data.length } : (d: number) => boolean
29+
>d : number
30+
31+
return d === this.data.length
32+
>d === this.data.length : boolean
33+
>d : number
34+
>this.data.length : any
35+
>this.data : any
36+
>this : any
37+
>data : any
38+
>length : any
39+
40+
})
41+
}
42+
43+
forEacherRaw() {
44+
>forEacherRaw : () => void
45+
46+
this.data.forEach(function (d) {
47+
>this.data.forEach(function (d) { console.log(d === this.data.length) }) : void
48+
>this.data.forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void
49+
>this.data : number[]
50+
>this : this
51+
>data : number[]
52+
>forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void
53+
>function (d) { console.log(d === this.data.length) } : (d: number) => void
54+
>d : number
55+
56+
console.log(d === this.data.length)
57+
>console.log(d === this.data.length) : void
58+
>console.log : (...data: any[]) => void
59+
>console : Console
60+
>log : (...data: any[]) => void
61+
>d === this.data.length : boolean
62+
>d : number
63+
>this.data.length : any
64+
>this.data : any
65+
>this : any
66+
>data : any
67+
>length : any
68+
69+
})
70+
}
71+
72+
forEacher() {
73+
>forEacher : () => void
74+
75+
this.data.forEach(
76+
>this.data.forEach( /** @this {Test} */ function (d) { console.log(d === this.data.length) }, this) : void
77+
>this.data.forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void
78+
>this.data : number[]
79+
>this : this
80+
>data : number[]
81+
>forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void
82+
83+
/** @this {Test} */
84+
function (d) {
85+
>function (d) { console.log(d === this.data.length) } : (this: Test, d: number) => void
86+
>d : number
87+
88+
console.log(d === this.data.length)
89+
>console.log(d === this.data.length) : void
90+
>console.log : (...data: any[]) => void
91+
>console : Console
92+
>log : (...data: any[]) => void
93+
>d === this.data.length : boolean
94+
>d : number
95+
>this.data.length : number
96+
>this.data : number[]
97+
>this : Test
98+
>data : number[]
99+
>length : number
100+
101+
}, this)
102+
>this : this
103+
}
104+
105+
finder() {
106+
>finder : () => void
107+
108+
this.data.find(
109+
>this.data.find( /** @this {Test} */ function (d) { return d === this.data.length }, this) : number
110+
>this.data.find : { <S extends number>(predicate: (value: number, index: number, obj: number[]) => value is S, thisArg?: any): S; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }
111+
>this.data : number[]
112+
>this : this
113+
>data : number[]
114+
>find : { <S extends number>(predicate: (value: number, index: number, obj: number[]) => value is S, thisArg?: any): S; (predicate: (value: number, index: number, obj: number[]) => unknown, thisArg?: any): number; }
115+
116+
/** @this {Test} */
117+
function (d) {
118+
>function (d) { return d === this.data.length } : (this: Test, d: number) => boolean
119+
>d : number
120+
121+
return d === this.data.length
122+
>d === this.data.length : boolean
123+
>d : number
124+
>this.data.length : number
125+
>this.data : number[]
126+
>this : Test
127+
>data : number[]
128+
>length : number
129+
130+
}, this)
131+
>this : this
132+
}
133+
}
134+

0 commit comments

Comments
 (0)