Ch. 2 · TypeScript

TypeScript this Types and Fluent APIs

Use polymorphic this return types for builders, keep chaining correct through subclasses, and constrain this parameters.

~2 min readadvancedupdated Oct 5, 2026

A method that returns this keeps a fluent chain aware of the exact receiver type, including subclasses. Returning the base type instead breaks chaining as soon as a subclass adds a method, which is the difference between a builder that composes and one that does not.

Before you start

You should be comfortable with classes, inheritance and method signatures. This article covers polymorphic this types and this parameters; it assumes basic generic syntax.

Step-by-step walkthrough

Step 1: Return this, not the class name

Declaring where(clause: string): this makes the returned value keep the concrete type of the call site. A subclass call keeps the subclass type, so methods added by the subclass remain available after the call. Returning Query would narrow the chain back to the base type.

Step 2: Let subclasses extend the chain

Because this is polymorphic, a subclass method can also return this and the chain stays correct without redeclaring base methods. This is why this return types work with inheritance where a hard-coded class name does not.

Step 3: Constrain this for detached methods

A this parameter such as function clone(this: { id: string }) types how a method expects to be bound. It cannot appear in an arrow function, because arrows capture this lexically and have no binding to describe. Use it for helpers designed to be mixed into objects.

Worked scenario

The subclass keeps its own method after a base-chain call because the return type is this.

class Query {
  private parts: string[] = [];
  where(clause: string): this { this.parts.push(clause); return this; }
  build(): string { return this.parts.join(' AND '); }
}
class PagedQuery extends Query {
  limit(n: number): this { return this.where(`LIMIT ${n}`); }
}
const sql = new PagedQuery().where('a = 1').limit(10).build();
console.log(sql); // a = 1 AND LIMIT 10
TypeScript

Walk through the example

where returns this, which is PagedQuery at this call site, so .limit is available after it. limit also returns this, so .build still resolves. The order proves the chain type is the subclass throughout; returning Query from where would have hidden .limit and caused a compile error.

Common mistake

Returning the base class name from a fluent method, which drops subclass methods from the chain. Another mistake is writing a fluent method as an arrow function while trying to use a this parameter; arrows cannot declare one.

Verify the behavior

Build the chain in subclass order and confirm it compiles and produces the expected string. Then change where to return Query and confirm .limit becomes a compile error. Add a this parameter to a plain function and call it with .call on a compatible object to confirm it type-checks.

Interview exercise

Why does a builder returning BaseBuilder break subclass chaining, while returning this does not?

Answer and reasoning

Returning BaseBuilder erases the subclass type: after the call the compiler only knows the base methods, so subclass-specific methods are unavailable. this is a special type that resolves to the actual receiver type at each call site, so in a subclass context it is the subclass, and the chain keeps every available method. It is the type-system way to say “return whatever you were called on”.

Continue learning

Compare with function variance and generic constraints. Read the TypeScript polymorphic this handbook and try the TypeScript interview questions.

More in TypeScript

read ✓TypeScript · hard

TypeScript Abstract Classes and Contracts

Share behavior with abstract classes, enforce required members, and decide when an interface or composition is the better contract.

~2 min readread →
read ✓TypeScript · mid

TypeScript Enums vs Union Types

Compare enums with unions of string literals: runtime cost, serialization, exhaustiveness and which one fits application code.

~3 min readread →
esc