Skip to content

Commit df40c7a

Browse files
authored
fix(51868): this within function typed as any when annotated with JSDoc (#54516)
1 parent 38575dc commit df40c7a

File tree

5 files changed

+246
-10
lines changed

5 files changed

+246
-10
lines changed

src/compiler/checker.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28473,20 +28473,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2847328473
}
2847428474
}
2847528475

28476-
function getTypeForThisExpressionFromJSDoc(node: Node) {
28477-
const jsdocType = getJSDocType(node);
28478-
if (jsdocType && jsdocType.kind === SyntaxKind.JSDocFunctionType) {
28479-
const jsDocFunctionType = jsdocType as JSDocFunctionType;
28480-
if (jsDocFunctionType.parameters.length > 0 &&
28481-
jsDocFunctionType.parameters[0].name &&
28482-
(jsDocFunctionType.parameters[0].name as Identifier).escapedText === InternalSymbolName.This) {
28483-
return getTypeFromTypeNode(jsDocFunctionType.parameters[0].type!);
28484-
}
28485-
}
28476+
function getTypeForThisExpressionFromJSDoc(node: SignatureDeclaration) {
2848628477
const thisTag = getJSDocThisTag(node);
2848728478
if (thisTag && thisTag.typeExpression) {
2848828479
return getTypeFromTypeNode(thisTag.typeExpression);
2848928480
}
28481+
const signature = getSignatureOfTypeTag(node);
28482+
if (signature) {
28483+
return getThisTypeOfSignature(signature);
28484+
}
2849028485
}
2849128486

2849228487
function isInConstructorArgumentInitializer(node: Node, constructorDecl: Node): boolean {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/a.js(3,10): error TS2339: Property 'test' does not exist on type 'Foo'.
2+
/a.js(8,10): error TS2339: Property 'test' does not exist on type 'Foo'.
3+
/a.js(13,10): error TS2339: Property 'test' does not exist on type 'Foo'.
4+
/a.js(18,10): error TS2339: Property 'test' does not exist on type 'Foo'.
5+
/a.js(23,10): error TS2339: Property 'test' does not exist on type 'Foo'.
6+
/a.js(28,10): error TS2339: Property 'test' does not exist on type 'Foo'.
7+
8+
9+
==== /types.d.ts (0 errors) ====
10+
export interface Foo {
11+
foo: () => void;
12+
}
13+
14+
export type M = (this: Foo) => void;
15+
16+
==== /a.js (6 errors) ====
17+
/** @type {import('./types').M} */
18+
export const f1 = function() {
19+
this.test();
20+
~~~~
21+
!!! error TS2339: Property 'test' does not exist on type 'Foo'.
22+
}
23+
24+
/** @type {import('./types').M} */
25+
export function f2() {
26+
this.test();
27+
~~~~
28+
!!! error TS2339: Property 'test' does not exist on type 'Foo'.
29+
}
30+
31+
/** @type {(this: import('./types').Foo) => void} */
32+
export const f3 = function() {
33+
this.test();
34+
~~~~
35+
!!! error TS2339: Property 'test' does not exist on type 'Foo'.
36+
}
37+
38+
/** @type {(this: import('./types').Foo) => void} */
39+
export function f4() {
40+
this.test();
41+
~~~~
42+
!!! error TS2339: Property 'test' does not exist on type 'Foo'.
43+
}
44+
45+
/** @type {function(this: import('./types').Foo): void} */
46+
export const f5 = function() {
47+
this.test();
48+
~~~~
49+
!!! error TS2339: Property 'test' does not exist on type 'Foo'.
50+
}
51+
52+
/** @type {function(this: import('./types').Foo): void} */
53+
export function f6() {
54+
this.test();
55+
~~~~
56+
!!! error TS2339: Property 'test' does not exist on type 'Foo'.
57+
}
58+
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
=== /types.d.ts ===
2+
export interface Foo {
3+
>Foo : Symbol(Foo, Decl(types.d.ts, 0, 0))
4+
5+
foo: () => void;
6+
>foo : Symbol(Foo.foo, Decl(types.d.ts, 0, 22))
7+
}
8+
9+
export type M = (this: Foo) => void;
10+
>M : Symbol(M, Decl(types.d.ts, 2, 1))
11+
>this : Symbol(this, Decl(types.d.ts, 4, 17))
12+
>Foo : Symbol(Foo, Decl(types.d.ts, 0, 0))
13+
14+
=== /a.js ===
15+
/** @type {import('./types').M} */
16+
export const f1 = function() {
17+
>f1 : Symbol(f1, Decl(a.js, 1, 12))
18+
19+
this.test();
20+
>this : Symbol(this, Decl(types.d.ts, 4, 17))
21+
}
22+
23+
/** @type {import('./types').M} */
24+
export function f2() {
25+
>f2 : Symbol(f2, Decl(a.js, 3, 1))
26+
27+
this.test();
28+
>this : Symbol(Foo, Decl(types.d.ts, 0, 0))
29+
}
30+
31+
/** @type {(this: import('./types').Foo) => void} */
32+
export const f3 = function() {
33+
>f3 : Symbol(f3, Decl(a.js, 11, 12))
34+
35+
this.test();
36+
>this : Symbol(this, Decl(a.js, 10, 12))
37+
}
38+
39+
/** @type {(this: import('./types').Foo) => void} */
40+
export function f4() {
41+
>f4 : Symbol(f4, Decl(a.js, 13, 1))
42+
43+
this.test();
44+
>this : Symbol(Foo, Decl(types.d.ts, 0, 0))
45+
}
46+
47+
/** @type {function(this: import('./types').Foo): void} */
48+
export const f5 = function() {
49+
>f5 : Symbol(f5, Decl(a.js, 21, 12))
50+
51+
this.test();
52+
>this : Symbol(this, Decl(a.js, 20, 20))
53+
}
54+
55+
/** @type {function(this: import('./types').Foo): void} */
56+
export function f6() {
57+
>f6 : Symbol(f6, Decl(a.js, 23, 1))
58+
59+
this.test();
60+
>this : Symbol(Foo, Decl(types.d.ts, 0, 0))
61+
}
62+
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
=== /types.d.ts ===
2+
export interface Foo {
3+
foo: () => void;
4+
>foo : () => void
5+
}
6+
7+
export type M = (this: Foo) => void;
8+
>M : (this: Foo) => void
9+
>this : Foo
10+
11+
=== /a.js ===
12+
/** @type {import('./types').M} */
13+
export const f1 = function() {
14+
>f1 : import("/types").M
15+
>function() { this.test();} : (this: import("/types").Foo) => void
16+
17+
this.test();
18+
>this.test() : any
19+
>this.test : any
20+
>this : import("/types").Foo
21+
>test : any
22+
}
23+
24+
/** @type {import('./types').M} */
25+
export function f2() {
26+
>f2 : (this: import("/types").Foo) => void
27+
28+
this.test();
29+
>this.test() : any
30+
>this.test : any
31+
>this : import("/types").Foo
32+
>test : any
33+
}
34+
35+
/** @type {(this: import('./types').Foo) => void} */
36+
export const f3 = function() {
37+
>f3 : (this: import("/types").Foo) => void
38+
>function() { this.test();} : (this: import("/types").Foo) => void
39+
40+
this.test();
41+
>this.test() : any
42+
>this.test : any
43+
>this : import("/types").Foo
44+
>test : any
45+
}
46+
47+
/** @type {(this: import('./types').Foo) => void} */
48+
export function f4() {
49+
>f4 : (this: import('./types').Foo) => void
50+
51+
this.test();
52+
>this.test() : any
53+
>this.test : any
54+
>this : import("/types").Foo
55+
>test : any
56+
}
57+
58+
/** @type {function(this: import('./types').Foo): void} */
59+
export const f5 = function() {
60+
>f5 : (this: import("/types").Foo) => void
61+
>function() { this.test();} : (this: import("/types").Foo) => void
62+
63+
this.test();
64+
>this.test() : any
65+
>this.test : any
66+
>this : import("/types").Foo
67+
>test : any
68+
}
69+
70+
/** @type {function(this: import('./types').Foo): void} */
71+
export function f6() {
72+
>f6 : (this: import('./types').Foo) => void
73+
74+
this.test();
75+
>this.test() : any
76+
>this.test : any
77+
>this : import("/types").Foo
78+
>test : any
79+
}
80+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// @allowJs: true
2+
// @checkJs: true
3+
// @noEmit: true
4+
5+
// @filename: /types.d.ts
6+
export interface Foo {
7+
foo: () => void;
8+
}
9+
10+
export type M = (this: Foo) => void;
11+
12+
// @filename: /a.js
13+
/** @type {import('./types').M} */
14+
export const f1 = function() {
15+
this.test();
16+
}
17+
18+
/** @type {import('./types').M} */
19+
export function f2() {
20+
this.test();
21+
}
22+
23+
/** @type {(this: import('./types').Foo) => void} */
24+
export const f3 = function() {
25+
this.test();
26+
}
27+
28+
/** @type {(this: import('./types').Foo) => void} */
29+
export function f4() {
30+
this.test();
31+
}
32+
33+
/** @type {function(this: import('./types').Foo): void} */
34+
export const f5 = function() {
35+
this.test();
36+
}
37+
38+
/** @type {function(this: import('./types').Foo): void} */
39+
export function f6() {
40+
this.test();
41+
}

0 commit comments

Comments
 (0)