Skip to content

Commit cc3d011

Browse files
authored
Infer this parameters (#26800)
Previously we didn't. I can't remember why, probably because I overlooked it in the initial PR.
1 parent d293b67 commit cc3d011

File tree

5 files changed

+112
-0
lines changed

5 files changed

+112
-0
lines changed

src/compiler/checker.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13074,6 +13074,14 @@ namespace ts {
1307413074
const paramCount = targetRestType ? Math.min(targetCount - 1, sourceCount) :
1307513075
sourceRestType ? targetCount :
1307613076
Math.min(sourceCount, targetCount);
13077+
13078+
const sourceThisType = getThisTypeOfSignature(source);
13079+
if (sourceThisType) {
13080+
const targetThisType = getThisTypeOfSignature(target);
13081+
if (targetThisType) {
13082+
callback(sourceThisType, targetThisType);
13083+
}
13084+
}
1307713085
for (let i = 0; i < paramCount; i++) {
1307813086
callback(getTypeAtPosition(source, i), getTypeAtPosition(target, i));
1307913087
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//// [inferThisType.ts]
2+
declare function f<T>(g: (this: T) => void): T
3+
declare function h(this: number): void;
4+
f(h)
5+
6+
// works with infer types as well
7+
type Check<T> = T extends (this: infer U, ...args: any[]) => any ? string : unknown;
8+
type r1 = Check<(this: number) => void>; // should be string
9+
10+
type This<T> = T extends (this: infer U, ...args: any[]) => any ? U : unknown;
11+
type r2 = This<(this: number) => void>; // should be number
12+
13+
14+
//// [inferThisType.js]
15+
f(h);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
=== tests/cases/conformance/types/thisType/inferThisType.ts ===
2+
declare function f<T>(g: (this: T) => void): T
3+
>f : Symbol(f, Decl(inferThisType.ts, 0, 0))
4+
>T : Symbol(T, Decl(inferThisType.ts, 0, 19))
5+
>g : Symbol(g, Decl(inferThisType.ts, 0, 22))
6+
>this : Symbol(this, Decl(inferThisType.ts, 0, 26))
7+
>T : Symbol(T, Decl(inferThisType.ts, 0, 19))
8+
>T : Symbol(T, Decl(inferThisType.ts, 0, 19))
9+
10+
declare function h(this: number): void;
11+
>h : Symbol(h, Decl(inferThisType.ts, 0, 46))
12+
>this : Symbol(this, Decl(inferThisType.ts, 1, 19))
13+
14+
f(h)
15+
>f : Symbol(f, Decl(inferThisType.ts, 0, 0))
16+
>h : Symbol(h, Decl(inferThisType.ts, 0, 46))
17+
18+
// works with infer types as well
19+
type Check<T> = T extends (this: infer U, ...args: any[]) => any ? string : unknown;
20+
>Check : Symbol(Check, Decl(inferThisType.ts, 2, 4))
21+
>T : Symbol(T, Decl(inferThisType.ts, 5, 11))
22+
>T : Symbol(T, Decl(inferThisType.ts, 5, 11))
23+
>this : Symbol(this, Decl(inferThisType.ts, 5, 27))
24+
>U : Symbol(U, Decl(inferThisType.ts, 5, 38))
25+
>args : Symbol(args, Decl(inferThisType.ts, 5, 41))
26+
27+
type r1 = Check<(this: number) => void>; // should be string
28+
>r1 : Symbol(r1, Decl(inferThisType.ts, 5, 84))
29+
>Check : Symbol(Check, Decl(inferThisType.ts, 2, 4))
30+
>this : Symbol(this, Decl(inferThisType.ts, 6, 17))
31+
32+
type This<T> = T extends (this: infer U, ...args: any[]) => any ? U : unknown;
33+
>This : Symbol(This, Decl(inferThisType.ts, 6, 40))
34+
>T : Symbol(T, Decl(inferThisType.ts, 8, 10))
35+
>T : Symbol(T, Decl(inferThisType.ts, 8, 10))
36+
>this : Symbol(this, Decl(inferThisType.ts, 8, 27))
37+
>U : Symbol(U, Decl(inferThisType.ts, 8, 38))
38+
>args : Symbol(args, Decl(inferThisType.ts, 8, 41))
39+
>U : Symbol(U, Decl(inferThisType.ts, 8, 38))
40+
41+
type r2 = This<(this: number) => void>; // should be number
42+
>r2 : Symbol(r2, Decl(inferThisType.ts, 8, 79))
43+
>This : Symbol(This, Decl(inferThisType.ts, 6, 40))
44+
>this : Symbol(this, Decl(inferThisType.ts, 9, 16))
45+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
=== tests/cases/conformance/types/thisType/inferThisType.ts ===
2+
declare function f<T>(g: (this: T) => void): T
3+
>f : <T>(g: (this: T) => void) => T
4+
>g : (this: T) => void
5+
>this : T
6+
7+
declare function h(this: number): void;
8+
>h : (this: number) => void
9+
>this : number
10+
11+
f(h)
12+
>f(h) : number
13+
>f : <T>(g: (this: T) => void) => T
14+
>h : (this: number) => void
15+
16+
// works with infer types as well
17+
type Check<T> = T extends (this: infer U, ...args: any[]) => any ? string : unknown;
18+
>Check : Check<T>
19+
>this : U
20+
>args : any[]
21+
22+
type r1 = Check<(this: number) => void>; // should be string
23+
>r1 : string
24+
>this : number
25+
26+
type This<T> = T extends (this: infer U, ...args: any[]) => any ? U : unknown;
27+
>This : This<T>
28+
>this : U
29+
>args : any[]
30+
31+
type r2 = This<(this: number) => void>; // should be number
32+
>r2 : number
33+
>this : number
34+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
declare function f<T>(g: (this: T) => void): T
2+
declare function h(this: number): void;
3+
f(h)
4+
5+
// works with infer types as well
6+
type Check<T> = T extends (this: infer U, ...args: any[]) => any ? string : unknown;
7+
type r1 = Check<(this: number) => void>; // should be string
8+
9+
type This<T> = T extends (this: infer U, ...args: any[]) => any ? U : unknown;
10+
type r2 = This<(this: number) => void>; // should be number

0 commit comments

Comments
 (0)