Skip to content

Commit a47ac63

Browse files
authored
Fix for incorrect 'this' type for optional call (#33799)
1 parent e9b464e commit a47ac63

File tree

5 files changed

+72
-1
lines changed

5 files changed

+72
-1
lines changed

src/compiler/checker.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23593,7 +23593,20 @@ namespace ts {
2359323593
// If the signature's 'this' type is voidType, then the check is skipped -- anything is compatible.
2359423594
// If the expression is a new expression, then the check is skipped.
2359523595
const thisArgumentNode = getThisArgumentOfCall(node);
23596-
const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType;
23596+
let thisArgumentType: Type;
23597+
if (thisArgumentNode) {
23598+
thisArgumentType = checkExpression(thisArgumentNode);
23599+
if (isOptionalChainRoot(thisArgumentNode.parent)) {
23600+
thisArgumentType = getNonNullableType(thisArgumentType);
23601+
}
23602+
else if (isOptionalChain(thisArgumentNode.parent)) {
23603+
thisArgumentType = removeOptionalTypeMarker(thisArgumentType);
23604+
}
23605+
}
23606+
else {
23607+
thisArgumentType = voidType;
23608+
}
23609+
2359723610
const errorNode = reportErrors ? (thisArgumentNode || node) : undefined;
2359823611
const headMessage = Diagnostics.The_this_context_of_type_0_is_not_assignable_to_method_s_this_of_type_1;
2359923612
if (!checkTypeRelatedTo(thisArgumentType, thisType, relation, errorNode, headMessage, containingMessageChain, errorOutputContainer)) {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//// [thisTypeOptionalCall.ts]
2+
function maybeBind<T, A extends any[], R>(obj: T, fn: ((this: T, ...args: A) => R) | undefined): ((...args: A) => R) | undefined {
3+
return fn?.bind(obj);
4+
}
5+
6+
//// [thisTypeOptionalCall.js]
7+
function maybeBind(obj, fn) {
8+
var _a;
9+
return (_a = fn) === null || _a === void 0 ? void 0 : _a.bind(obj);
10+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
=== tests/cases/conformance/types/thisType/thisTypeOptionalCall.ts ===
2+
function maybeBind<T, A extends any[], R>(obj: T, fn: ((this: T, ...args: A) => R) | undefined): ((...args: A) => R) | undefined {
3+
>maybeBind : Symbol(maybeBind, Decl(thisTypeOptionalCall.ts, 0, 0))
4+
>T : Symbol(T, Decl(thisTypeOptionalCall.ts, 0, 19))
5+
>A : Symbol(A, Decl(thisTypeOptionalCall.ts, 0, 21))
6+
>R : Symbol(R, Decl(thisTypeOptionalCall.ts, 0, 38))
7+
>obj : Symbol(obj, Decl(thisTypeOptionalCall.ts, 0, 42))
8+
>T : Symbol(T, Decl(thisTypeOptionalCall.ts, 0, 19))
9+
>fn : Symbol(fn, Decl(thisTypeOptionalCall.ts, 0, 49))
10+
>this : Symbol(this, Decl(thisTypeOptionalCall.ts, 0, 56))
11+
>T : Symbol(T, Decl(thisTypeOptionalCall.ts, 0, 19))
12+
>args : Symbol(args, Decl(thisTypeOptionalCall.ts, 0, 64))
13+
>A : Symbol(A, Decl(thisTypeOptionalCall.ts, 0, 21))
14+
>R : Symbol(R, Decl(thisTypeOptionalCall.ts, 0, 38))
15+
>args : Symbol(args, Decl(thisTypeOptionalCall.ts, 0, 99))
16+
>A : Symbol(A, Decl(thisTypeOptionalCall.ts, 0, 21))
17+
>R : Symbol(R, Decl(thisTypeOptionalCall.ts, 0, 38))
18+
19+
return fn?.bind(obj);
20+
>fn?.bind : Symbol(Function.bind, Decl(lib.es5.d.ts, --, --))
21+
>fn : Symbol(fn, Decl(thisTypeOptionalCall.ts, 0, 49))
22+
>bind : Symbol(Function.bind, Decl(lib.es5.d.ts, --, --))
23+
>obj : Symbol(obj, Decl(thisTypeOptionalCall.ts, 0, 42))
24+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
=== tests/cases/conformance/types/thisType/thisTypeOptionalCall.ts ===
2+
function maybeBind<T, A extends any[], R>(obj: T, fn: ((this: T, ...args: A) => R) | undefined): ((...args: A) => R) | undefined {
3+
>maybeBind : <T, A extends any[], R>(obj: T, fn: ((this: T, ...args: A) => R) | undefined) => ((...args: A) => R) | undefined
4+
>obj : T
5+
>fn : ((this: T, ...args: A) => R) | undefined
6+
>this : T
7+
>args : A
8+
>args : A
9+
10+
return fn?.bind(obj);
11+
>fn?.bind(obj) : any
12+
>fn?.bind : ((this: Function, thisArg: any, ...argArray: any[]) => any) | undefined
13+
>fn : ((this: T, ...args: A) => R) | undefined
14+
>bind : ((this: Function, thisArg: any, ...argArray: any[]) => any) | undefined
15+
>obj : T
16+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// @strictNullChecks: true
2+
// @noImplicitAny: true
3+
// @noImplicitThis: true
4+
// @strictBindCallApply: false
5+
6+
function maybeBind<T, A extends any[], R>(obj: T, fn: ((this: T, ...args: A) => R) | undefined): ((...args: A) => R) | undefined {
7+
return fn?.bind(obj);
8+
}

0 commit comments

Comments
 (0)