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.
Example
#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)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
#class Class {
method(): this {
return this
}
}
function name(this: Type, arg: string) { ⊠}More examples
#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'.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'.Lesson: Flexbox (14 min) Module: Grid (16 min)
Good practices
#- Type chainable methods that end with
return thisas: this, not with the class name. That way derived classes donât lose their methods in the middle of the chain. - The
thisparameter must come first in the list and doesnât count as an argument. Arrow functions have nothisof 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). Instrictmode, usingthiswithout this annotation is an error.
Related entries
#- Function typesTyping parameters, the return value, and functions themselves as values.
- Type guards (value is T)Custom checking functions that narrow the type at the call site.
- public, private, protectedAccess modifiers that control where a classâs fields and methods can be used from.
- abstract classA base class you canât create directly, with methods for its descendants to fill in.
- implementsA declaration that a class fulfills the contract described by an interface.
Spotted a mistake or missing an example? Write to us.