How to fix 'this' context of type 'X' is not assignable to method's 'this' of type 'Y' in TypeScript
TypeScript throws this error when a method is invoked with a `this` binding that does not match its declared `this` parameter (common when methods are extracted or passed as callbacks). Align the call site by keeping the method bound, declaring explicit `this` parameters, or narrowing/binding the callback before invoking.
Quick fix
Fixes TS2684
const pickCard = deck.createCardPicker;
const card = pickCard(); // ERROR: this === undefined- Keep the method call bound to the object (or bind it manually)
- Declare an explicit `this` parameter for the method
- Match callback `this` annotations before passing instance methods
- Narrow unioned functions before calling `call/apply`
const pickCard = deck.createCardPicker;const card = pickCard(); // ERROR: this === undefined'this' context of type 'X' is not assignable to method's 'this' of type 'Y'
What this error means
The compiler gives you this error when it can prove that the `this` value used for a method is incompatible with the method's declared `this` parameter (see the handbook section on `this` parameters). When a method is defined like `createCardPicker(this: Deck)`, TypeScript now knows the method expects to run on a Deck instance, so any invocation that supplies a different `this`—for example because the method was grabbed as a callback or a Function union—trips the error. This is part of `noImplicitThis` and the explicit `this` parameter rules that keep you from walking into runtime bugs where `this` is `undefined` or missing the properties your method reads.
Typical symptoms
- Compiler stops with TS2684: 'this context of type ... is not assignable to method's 'this''.
- Code runs fine when calling the method directly on the object but fails when the method is extracted or passed to setTimeout, event handlers, etc.
- Passing the method as a callback produces the same error because the library calls it with `this: void` or `undefined`.
- The editor underlines the call expression even though the object has the expected members.
- The failure usually shows up after refactoring a method into a standalone helper or after switching to strict `noImplicitThis` settings.
Common causes
- You stored a method in a variable (e.g., `const pickCard = deck.createCardPicker`) and then invoked it, so `this` becomes `undefined` rather than the owning object.
- A callback signature from a library expects `this: void` but you pass a method that reads instance properties and needs a richer `this`.
- The method declares an explicit `this` parameter but you call it through `Function.prototype.call/apply` with an incompatible context.
- You expose a union type that contains `Function` alongside more specific call signatures, so TypeScript refuses to satisfy the method's declared `this` before it tries to widen the union.
- Strict `noImplicitThis` is on, so the compiler becomes more aggressive about tracking the context for every function and method.
How to fix "'this' context of type 'X' is not assignable to method's 'this' of type 'Y'"
Extracting the method breaks its implicit this binding. Call it directly on the deck (or bind the method) so the context stays intact:
Broken
const pickCard = deck.createCardPicker;
const card = pickCard(); // ERROR: this === undefinedFixed
const cardPicker = deck.createCardPicker();
const card = cardPicker(); // this === deck
// Or bind the context explicitly:
const cardPicker = deck.createCardPicker.bind(deck);Keeping the call on the object (or using .bind(deck)) ensures TypeScript sees the correct this type before invoking the method.
The Handbook recommends faking a leading this parameter to document the expected context:
interface Deck {
suits: string[];
cards: number[];
createCardPicker(this: Deck): () => Card;
}
const deck: Deck = { ... };
deck.createCardPicker(); // TypeScript now knows `this` is DeckAdding this: Deck keeps noImplicitThis happy and prevents any call from supplying an incompatible context because the compiler requires the receiver to match Deck before the method executes.
Many DOM or helper APIs call your callback with this: void.
If your handler reads this, the compiler will reject the assignment:
interface UIElement {
addClickListener(onclick: (this: void, e: Event) => void): void;
}
class Handler {
info = "ready";
onClickBad(this: Handler, e: Event) {
this.info = e.message;
}
}
const handler = new Handler();
uiElement.addClickListener(handler.onClickBad); // ERROR: this void ≠ HandlerFix the mismatch by rewriting the callback to avoid this or by binding it:
uiElement.addClickListener((e) => handler.onClickBad(e)); // arrow keeps Handler as `this`
uiElement.addClickListener(handler.onClickBad.bind(handler));Now the callable signature aligns with this: void, so the compiler is satisfied.
A union type that contains Function can make the compiler lose track of the expected this. For example:
type Test1Type<V> = object | ((this: V, arg: V) => object);
function invoke<V>(test1Fnc: Test1Type<V>, value: V) {
if (typeof test1Fnc === "function") {
const safeFn = test1Fnc as (this: V, arg: V) => object;
return safeFn.call(value, value);
}
}If you skip the type guard (or the cast), TypeScript will refuse to call test1Fnc because the union could be an object that does not provide the required this type. Narrow dedicated call signatures or cast after a guard so this stays compatible before calling.
Advanced notes
When a union type mixes Function with more specific call signatures, the compiler tries to assign the union to the method signature before letting Function relax the this requirement. The result is the same error even though at runtime one branch would work. Redefine the union with precise this annotations or cast after a guard so TypeScript can prove the correct this before invoking the method.
Frequently asked questions
- What does "TS2684" mean?
- The compiler gives you this error when it can prove that the this value used for a method is incompatible with the method's declared this parameter (see the handbook section on this parameters). When a method is defined like createCardPicker(this: Deck), TypeScript now knows the method expects to run on a Deck instance, so any invocation that supplies a different this—for example because the method was grabbed as a callback or a Function union—trips the error. This is part of noImplicitThis and the explicit this parameter rules that keep you from walking into runtime bugs where this is undefined or missing the properties your method reads.
- How do I fix "TS2684"?
- TypeScript throws this error when a method is invoked with a this binding that does not match its declared this parameter (common when methods are extracted or passed as callbacks). Align the call site by keeping the method bound, declaring explicit this parameters, or narrowing/binding the callback before invoking.
- What causes "TS2684"?
- You stored a method in a variable (e.g., const pickCard = deck.createCardPicker) and then invoked it, so this becomes undefined rather than the owning object. A callback signature from a library expects this: void but you pass a method that reads instance properties and needs a richer this. The method declares an explicit this parameter but you call it through Function.prototype.call/apply with an incompatible context.
- Is the "TS2684" error serious?
- It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.