this as a type

The this type means the object a method was called on, and the this parameter describes the context of a regular function.

On this page

Example

#
TypeScript
class NotificationBuilder {
  protected parts: string[] = []

  title(text: string): this {
    this.parts.push(text.toUpperCase())
    return this
  }

  line(text: string): this {
    this.parts.push(text)
    return this
  }

  build(): string {
    return this.parts.join(' | ')
  }
}

class RewardNotification extends NotificationBuilder {
  exp(points: number): this {
    return this.line(`+${points} EXP`)
  }
}

const message = new RewardNotification().title('Task completed').exp(20).line('Keep it up!').build()
console.log(message)
Result
TASK COMPLETED | +20 EXP | Keep it up!

Definition and usage

#

In a type position, the word this means the type of the object a method was called on. A method with the return type this therefore returns not the class it was written in, but the class of the actual object. That way a call chain such as builder.title(
).line(
) keeps the methods of derived classes.

The second use is the this parameter: a fake first parameter of a function, e.g. function lessonLabel(this: Lesson, prefix: string). You don’t pass it when calling, and it disappears after compilation. Instead, the compiler checks that the function was called with the right object, for example through call() or as a method of an object.

The this type also appears in method predicates (isDone(): this is DoneTask) and in interfaces. With the noImplicitThis option, which is part of strict mode, using this in a regular function without a declared type fails with the error “'this' implicitly has type 'any' because it does not have a type annotation”.

Syntax

#
Syntax
class Class {
  method(): this {
    return this
  }
}

function name(this: Type, arg: string) { 
 }

More examples

#
A method that returns the base class
TypeScript
class PlainBuilder {
  line(text: string): PlainBuilder {
    return this
  }
}

class BadgeBuilder extends PlainBuilder {
  badge(name: string): BadgeBuilder {
    return this
  }
}

new BadgeBuilder().line('Well done').badge('7-day streak')
// Error: Property 'badge' does not exist on type 'PlainBuilder'.
The this parameter
TypeScript
interface Lesson {
  title: string
  minutes: number
}

function lessonLabel(this: Lesson, prefix: string): string {
  return `${prefix} ${this.title} (${this.minutes} min)`
}

const flexbox: Lesson = { title: 'Flexbox', minutes: 14 }
console.log(lessonLabel.call(flexbox, 'Lesson:'))

const grid = { title: 'Grid', minutes: 16, label: lessonLabel }
console.log(grid.label('Module:'))

// lessonLabel('Lesson:')
// Error: The 'this' context of type 'void' is not assignable to method's 'this' of type 'Lesson'.
Result
Lesson: Flexbox (14 min)
Module: Grid (16 min)

Good practices

#
  • Type chainable methods that end with return this as : this, not with the class name. That way derived classes don’t lose their methods in the middle of the chain.
  • The this parameter must come first in the list and doesn’t count as an argument. Arrow functions have no this of their own, so they can’t declare it: the compiler reports “An arrow function cannot have a 'this' parameter”.
  • For a separately declared event handler that uses this, describe it with a parameter: function onClick(this: HTMLButtonElement). In strict mode, using this without this annotation is an error.

Related entries

#

Spotted a mistake or missing an example? Write to us.