TS2683 fires when strict mode or the `noImplicitThis` compiler option is on and the compiler cannot infer a `this` type. Annotating `this`, keeping the lexical context (arrow functions), or binding callbacks gives the compiler the missing context so the error disappears.
TypeScript's "this implicitly has type 'any'" error is emitted whenever you refer to `this` in a normal function and the compiler, guided by `noImplicitThis` or the wider `strict` family, cannot infer which object it should point to. Instead of silently treating `this` as `any`, the compiler raises TS2683 so you either declare a fake `this` parameter, keep the lexical `this` through arrow functions, or otherwise bind the function to an object before use. The message helps you avoid the runtime trap where `this` ends up `undefined` or `window` when a library calls your callback without the right context.
TypeScript lets you describe the expected this type by adding a fake first parameter. The parameter disappears at runtime but keeps the compiler satisfied:
interface Deck {
suits: string[];
cards: number[];
createCardPicker(this: Deck): () => Card;
}
const deck: Deck = {
suits: ["hearts", "spades", "clubs", "diamonds"],
cards: Array(52),
createCardPicker(this: Deck) {
return () => ({
suit: this.suits[Math.floor(Math.random() * this.suits.length)],
card: Math.floor(Math.random() * 13) + 1,
});
},
};
const cardPicker = deck.createCardPicker();
const card = cardPicker();
console.log(card);When the compiler knows this is a Deck, it no longer assumes any and TS2683 disappears even when you return the callback or pass it around.
Avoid creating plain function expressions that rely on this. Arrow functions inherit the surrounding this, and .bind/.call keeps the context in place:
class Rectangle {
constructor(public width: number, public height: number) {}
getAreaFunction() {
// Arrow function keeps `this` from the class instance and never triggers TS2683
return () => this.width * this.height;
}
}
const rect = new Rectangle(4, 5);
const getArea = rect.getAreaFunction();
console.log(getArea());The arrow function shares the class this, so no extra annotation is needed. When the API expects a normal function, call .bind(this) before handing it over so TypeScript sees a concrete context instead of implicit any.
Keep noImplicitThis turned on so that untyped this expressions stand out. In tsconfig.json:
{
"compilerOptions": {
"strict": true,
"noImplicitThis": true,
"target": "ES2020"
}
}Enabling strict also flips noImplicitThis. For legacy code you can temporarily set noImplicitThis to false and annotate the specific functions, but the goal should be to type every this, then restart the TypeScript server (e.g., "TypeScript: Restart TS Server" in VS Code) so the new rules take effect.
- The this parameter is a compile-time-only argument that always appears before the real parameters. It does not emit any runtime code but lets you constrain the calling context (e.g., this: Handler or this: void).
- Without noImplicitThis, the compiler silently treats untyped this expressions as any, masking bugs. Keeping noImplicitThis enabled (via strict) makes the compiler enforce contextual typing before the code runs.
Function expression requires a return type
Function expression requires a return type
Value of type 'string | undefined' is not iterable
How to fix "Value is not iterable" in TypeScript
Type 'undefined' is not assignable to type 'string'
How to fix "Type undefined is not assignable to type string" in TypeScript
Type narrowing from typeof check produces 'never'
How to fix "Type narrowing produces never" in TypeScript
Type parameter 'T' has conflicting constraints
How to fix "Type parameter has conflicting constraints" in TypeScript