fix(52594): this incorrectly applies in TS files in typeToString (#52610)

This commit is contained in:
Oleksandr T 2023-02-06 18:59:32 +02:00 committed by GitHub
parent 0bf99914e7
commit 70d14f3de2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 406 additions and 3 deletions

View File

@ -7307,7 +7307,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
if (signature.thisParameter) {
return symbolToParameterDeclaration(signature.thisParameter, context);
}
if (signature.declaration) {
if (signature.declaration && isInJSFile(signature.declaration)) {
const thisTag = getJSDocThisTag(signature.declaration);
if (thisTag && thisTag.typeExpression) {
return factory.createParameterDeclaration(

View File

@ -0,0 +1,68 @@
=== /a.ts ===
// /** @this {number} */
// function f() {
// ^
// | ----------------------------------------------------------------------
// | function f(): void
// | @this
// | ----------------------------------------------------------------------
// this
// }
[
{
"marker": {
"fileName": "/a.ts",
"position": 32,
"name": ""
},
"item": {
"kind": "function",
"kindModifiers": "",
"textSpan": {
"start": 31,
"length": 1
},
"displayParts": [
{
"text": "function",
"kind": "keyword"
},
{
"text": " ",
"kind": "space"
},
{
"text": "f",
"kind": "functionName"
},
{
"text": "(",
"kind": "punctuation"
},
{
"text": ")",
"kind": "punctuation"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "void",
"kind": "keyword"
}
],
"documentation": [],
"tags": [
{
"name": "this"
}
]
}
}
]

View File

@ -84,7 +84,7 @@ class Test {
/** @this {Test} */
function (d) {
>function (d) { console.log(d === this.data.length) } : (this: Test, d: number) => void
>function (d) { console.log(d === this.data.length) } : (d: number) => void
>d : number
console.log(d === this.data.length)
@ -117,7 +117,7 @@ class Test {
/** @this {Test} */
function (d) {
>function (d) { return d === this.data.length } : (this: Test, d: number) => boolean
>function (d) { return d === this.data.length } : (d: number) => boolean
>d : number
return d === this.data.length

View File

@ -0,0 +1,46 @@
/a.js(9,26): error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
/a.js(15,31): error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
==== /a.js (2 errors) ====
class Test {
constructor() {
/** @type {number[]} */
this.data = [1, 2, 3];
}
finderRaw() {
this.data.find(function (d) {
return d === this.data.length
~~~~
!!! error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
!!! related TS2738 /a.js:8:24: An outer value of 'this' is shadowed by this container.
})
}
forEacherRaw() {
this.data.forEach(function (d) {
console.log(d === this.data.length)
~~~~
!!! error TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
!!! related TS2738 /a.js:14:27: An outer value of 'this' is shadowed by this container.
})
}
forEacher() {
this.data.forEach(
/** @this {Test} */
function (d) {
console.log(d === this.data.length)
}, this)
}
finder() {
this.data.find(
/** @this {Test} */
function (d) {
return d === this.data.length
}, this)
}
}

View File

@ -0,0 +1,105 @@
=== /a.js ===
class Test {
>Test : Symbol(Test, Decl(a.js, 0, 0))
constructor() {
/** @type {number[]} */
this.data = [1, 2, 3];
>this.data : Symbol(Test.data, Decl(a.js, 1, 19))
>this : Symbol(Test, Decl(a.js, 0, 0))
>data : Symbol(Test.data, Decl(a.js, 1, 19))
}
finderRaw() {
>finderRaw : Symbol(Test.finderRaw, Decl(a.js, 4, 5))
this.data.find(function (d) {
>this.data.find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
>this.data : Symbol(Test.data, Decl(a.js, 1, 19))
>this : Symbol(Test, Decl(a.js, 0, 0))
>data : Symbol(Test.data, Decl(a.js, 1, 19))
>find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
>d : Symbol(d, Decl(a.js, 7, 33))
return d === this.data.length
>d : Symbol(d, Decl(a.js, 7, 33))
})
}
forEacherRaw() {
>forEacherRaw : Symbol(Test.forEacherRaw, Decl(a.js, 10, 5))
this.data.forEach(function (d) {
>this.data.forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --))
>this.data : Symbol(Test.data, Decl(a.js, 1, 19))
>this : Symbol(Test, Decl(a.js, 0, 0))
>data : Symbol(Test.data, Decl(a.js, 1, 19))
>forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --))
>d : Symbol(d, Decl(a.js, 13, 36))
console.log(d === this.data.length)
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>d : Symbol(d, Decl(a.js, 13, 36))
})
}
forEacher() {
>forEacher : Symbol(Test.forEacher, Decl(a.js, 16, 5))
this.data.forEach(
>this.data.forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --))
>this.data : Symbol(Test.data, Decl(a.js, 1, 19))
>this : Symbol(Test, Decl(a.js, 0, 0))
>data : Symbol(Test.data, Decl(a.js, 1, 19))
>forEach : Symbol(Array.forEach, Decl(lib.es5.d.ts, --, --))
/** @this {Test} */
function (d) {
>d : Symbol(d, Decl(a.js, 21, 18))
console.log(d === this.data.length)
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
>d : Symbol(d, Decl(a.js, 21, 18))
>this.data.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>this.data : Symbol(Test.data, Decl(a.js, 1, 19))
>this : Symbol(this)
>data : Symbol(Test.data, Decl(a.js, 1, 19))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
}, this)
>this : Symbol(Test, Decl(a.js, 0, 0))
}
finder() {
>finder : Symbol(Test.finder, Decl(a.js, 24, 5))
this.data.find(
>this.data.find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
>this.data : Symbol(Test.data, Decl(a.js, 1, 19))
>this : Symbol(Test, Decl(a.js, 0, 0))
>data : Symbol(Test.data, Decl(a.js, 1, 19))
>find : Symbol(Array.find, Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --))
/** @this {Test} */
function (d) {
>d : Symbol(d, Decl(a.js, 29, 18))
return d === this.data.length
>d : Symbol(d, Decl(a.js, 29, 18))
>this.data.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
>this.data : Symbol(Test.data, Decl(a.js, 1, 19))
>this : Symbol(this)
>data : Symbol(Test.data, Decl(a.js, 1, 19))
>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --))
}, this)
>this : Symbol(Test, Decl(a.js, 0, 0))
}
}

View File

@ -0,0 +1,134 @@
=== /a.js ===
class Test {
>Test : Test
constructor() {
/** @type {number[]} */
this.data = [1, 2, 3];
>this.data = [1, 2, 3] : number[]
>this.data : number[]
>this : this
>data : number[]
>[1, 2, 3] : number[]
>1 : 1
>2 : 2
>3 : 3
}
finderRaw() {
>finderRaw : () => void
this.data.find(function (d) {
>this.data.find(function (d) { return d === this.data.length }) : number
>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; }
>this.data : number[]
>this : this
>data : number[]
>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; }
>function (d) { return d === this.data.length } : (d: number) => boolean
>d : number
return d === this.data.length
>d === this.data.length : boolean
>d : number
>this.data.length : any
>this.data : any
>this : any
>data : any
>length : any
})
}
forEacherRaw() {
>forEacherRaw : () => void
this.data.forEach(function (d) {
>this.data.forEach(function (d) { console.log(d === this.data.length) }) : void
>this.data.forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void
>this.data : number[]
>this : this
>data : number[]
>forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void
>function (d) { console.log(d === this.data.length) } : (d: number) => void
>d : number
console.log(d === this.data.length)
>console.log(d === this.data.length) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>d === this.data.length : boolean
>d : number
>this.data.length : any
>this.data : any
>this : any
>data : any
>length : any
})
}
forEacher() {
>forEacher : () => void
this.data.forEach(
>this.data.forEach( /** @this {Test} */ function (d) { console.log(d === this.data.length) }, this) : void
>this.data.forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void
>this.data : number[]
>this : this
>data : number[]
>forEach : (callbackfn: (value: number, index: number, array: number[]) => void, thisArg?: any) => void
/** @this {Test} */
function (d) {
>function (d) { console.log(d === this.data.length) } : (this: Test, d: number) => void
>d : number
console.log(d === this.data.length)
>console.log(d === this.data.length) : void
>console.log : (...data: any[]) => void
>console : Console
>log : (...data: any[]) => void
>d === this.data.length : boolean
>d : number
>this.data.length : number
>this.data : number[]
>this : Test
>data : number[]
>length : number
}, this)
>this : this
}
finder() {
>finder : () => void
this.data.find(
>this.data.find( /** @this {Test} */ function (d) { return d === this.data.length }, this) : number
>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; }
>this.data : number[]
>this : this
>data : number[]
>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; }
/** @this {Test} */
function (d) {
>function (d) { return d === this.data.length } : (this: Test, d: number) => boolean
>d : number
return d === this.data.length
>d === this.data.length : boolean
>d : number
>this.data.length : number
>this.data : number[]
>this : Test
>data : number[]
>length : number
}, this)
>this : this
}
}

View File

@ -0,0 +1,41 @@
// @target: es2015
// @allowJs: true
// @checkJs: true
// @noEmit: true
// @noImplicitThis: true
// @filename: /a.js
class Test {
constructor() {
/** @type {number[]} */
this.data = [1, 2, 3];
}
finderRaw() {
this.data.find(function (d) {
return d === this.data.length
})
}
forEacherRaw() {
this.data.forEach(function (d) {
console.log(d === this.data.length)
})
}
forEacher() {
this.data.forEach(
/** @this {Test} */
function (d) {
console.log(d === this.data.length)
}, this)
}
finder() {
this.data.find(
/** @this {Test} */
function (d) {
return d === this.data.length
}, this)
}
}

View File

@ -0,0 +1,9 @@
/// <reference path="fourslash.ts" />
// @strict: true
// @filename: /a.ts
/////** @this {number} */
////function f/**/() {
//// this
////}
verify.baselineQuickInfo();