TypeScript Tracks What `this` Should Be
`this` Types
TS lets you type the `this` parameter inside a function. Useful for methods and callbacks that need a specific binding.
What you'll learn
- Type a `this` parameter
- Recognize when `this` becomes a problem
- Pick arrow functions to skip the issue
this is a JavaScript wart. TypeScript helps — you can declare
what this is expected to be.
The this Parameter
interface Counter {
count: number;
increment(this: Counter): void;
}
const c: Counter = {
count: 0,
increment(this: Counter) {
this.count++;
},
}; this: Counter isn’t a real parameter — it’s a type annotation
that says “when this method is called, this must be a Counter”.
TS verifies callers do that.
Why It Matters — The “Lost this” Bug
const inc = c.increment;
inc();
// ~~~ The 'this' context of type 'void' is not assignable to method's 'this' of type 'Counter'. Detaching a method loses this. TS catches this at compile time
when the method’s this is typed.
In Class Methods (Implicit)
Inside a class, methods know what this is automatically:
class Counter {
count = 0;
increment() {
this.count++; // this is Counter
}
} No need to declare this: Counter explicitly.
Arrow Functions Don’t Have Their Own this
class Timer {
count = 0;
start() {
setInterval(() => {
this.count++; // arrow function — this is the Timer instance
}, 1000);
}
} Arrow functions capture this from the enclosing scope. The
single best escape hatch from this weirdness.
this in Plain Functions
By default, this in a plain function is any. To require a
specific this:
function logName(this: { name: string }) {
console.log(this.name);
}
logName.call({ name: "Ada" }); // ✓
logName.call({}); // ✗ Property 'name' is missing Rare in app code; matters in libraries.
ThisParameterType and OmitThisParameter
Two utility types for working with this-typed functions —
useful when wrapping methods. We won’t dig in; just know they
exist.
Up Next
How TS infers function types from context.
Function Inference →