Skip to content
TypeScript ts functions 3 min read

Typing this in Functions

In JavaScript, the value of this inside a function depends on how the function is called, not where it is defined — a frequent source of bugs. TypeScript lets you type that calling context with a special fake this parameter: a parameter named this listed first in the signature. It exists only at compile time, is erased from the emitted JavaScript, and never counts as a real argument. This page covers declaring the this parameter, the utility types ThisParameterType and OmitThisParameter, and the noImplicitThis flag that surfaces unsafe usage.

The fake this parameter

You declare the expected context by adding this: Type as the very first parameter. It is purely a type annotation — callers still pass arguments starting from the second parameter.

interface Card {
  suit: string;
  value: number;
}

interface Deck {
  cards: Card[];
  describe(this: Deck): string;
}

const deck: Deck = {
  cards: [{ suit: "♠", value: 1 }],
  describe(this: Deck) {
    return `Deck of ${this.cards.length} cards`;
  },
};

deck.describe(); // ✅ called with the right context

Because this is the first parameter, describe still takes zero real arguments. TypeScript now checks that every call has a compatible receiver.

Catching the wrong context

The point of typing this is to reject calls where the context would be wrong at runtime — most commonly when a method is detached from its object and invoked standalone.

const describe = deck.describe;

// ❌ Error: The 'this' context of type 'void' is not assignable
//    to method's 'this' of type 'Deck'.
describe();

Pulling deck.describe into a bare variable loses the receiver, so calling it would make this undefined. The typed this parameter turns that latent runtime crash into a compile error.

Callbacks and the this type

The this parameter is especially valuable for callback APIs that invoke your function with a specific context — for example, older DOM event handlers where this is the element.

interface ClickHandler {
  (this: HTMLButtonElement, event: MouseEvent): void;
}

const onClick: ClickHandler = function (event) {
  this.disabled = true; // this: HTMLButtonElement
  console.log(event.clientX);
};

button.addEventListener("click", onClick);

Arrow functions have no this of their own — they capture it lexically — so you cannot declare a this parameter on one. Use a function expression when an API sets this for you.

ThisParameterType and OmitThisParameter

Two built-in utility types let you work with the declared context. ThisParameterType<T> extracts the this parameter’s type (or unknown if none), and OmitThisParameter<T> removes it, producing the type you would get after binding.

function describeDeck(this: Deck): string {
  return `Deck of ${this.cards.length} cards`;
}

type Ctx = ThisParameterType<typeof describeDeck>; // Deck
type Bound = OmitThisParameter<typeof describeDeck>; // () => string

const bound: Bound = describeDeck.bind(deck);
bound(); // no context required anymore

OmitThisParameter mirrors what Function.prototype.bind does at runtime: once bound, the function no longer needs (or accepts) an external this.

this types in classes and fluent APIs

Inside a class, the polymorphic this type (lowercase, distinct from the parameter) refers to the current instance type and powers fluent, chainable builders that return subclasses correctly.

class QueryBuilder {
  private parts: string[] = [];
  where(clause: string): this {
    this.parts.push(clause);
    return this;
  }
}

class AdminQuery extends QueryBuilder {
  asAdmin(): this {
    return this;
  }
}

new AdminQuery().where("active = 1").asAdmin(); // stays AdminQuery

Returning this rather than QueryBuilder keeps the subclass type through the chain.

ConstructPurpose
this: T parameterDeclare the required calling context (erased at runtime)
this return typeEnable fluent chaining that preserves the subclass
ThisParameterType<T>Extract the declared context type
OmitThisParameter<T>Produce the post-bind signature
noImplicitThisFlag functions where this is implicitly any

Enable noImplicitThis (included in strict) so any function relying on an untyped this becomes an error you must resolve explicitly.

Best Practices

  • Declare a this: Type parameter whenever a function depends on its calling context.
  • Remember the this parameter is fake — it is erased and never counts as a real argument.
  • Use function expressions, not arrow functions, when an API supplies this for you.
  • Enable noImplicitThis (via strict) to catch unsafe implicit this usage.
  • Return this from chainable methods so subclasses preserve their type through fluent calls.
  • Reach for OmitThisParameter to type the result of bind, and ThisParameterType to extract a context.
Last updated June 29, 2026
Was this helpful?