Pace
Pace

Reputation: 43817

Passing a class function as a callback and having this be set in typescript

In my express application I have controllers which look something like:

import * as express from 'express';
import { BooksService } from '../services';

export class BooksController {

  constructor (private booksService: BooksService) { }

  register(router: express.Router) {
    //LINE IN QUESTION
    router.get('/', (req, rsp, next) => this.getBooks(req, rsp, next));
  }

  private getBooks(req: express.Request, rsp: express.Response, next: express.NextFunction) {
    rsp.json(this.booksService.getAllBooks());
  }

}

However, I would really like to just write the line in question as:

router.get('/', this.getBooks);

...but of course then this will be undefined.

I can also make getBooks a stateless function outside the class:

function getBooks(booksService: BooksService) {
  return function(req: express.Request, rsp: express.Response, next: express.NextFunction) {
    rsp.json(booksService.getAllBooks());
  };
}

Which allows me to rewrite the line in question as:

router.get('/', getBooks(this.booksService));

...but that is still a tedious amount of boilerplate, especially if getBooks requires access to more than one instance variable.

Is there any way I can pass this.getBooks as a callback to express so that this will be defined when it is called? I feel like I'm missing something simple.

Upvotes: 0

Views: 160

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249536

You can define getBooks as a field of type function, and assign it an arrow function, thus capturing the correct this:

export class BooksController {

  constructor (private booksService: BooksService) { }

  register(router: express.Router) {
    router.get('/', this.getBooks);
  }

  private getBooks = (req: express.Request, rsp: express.Response, next: express.NextFunction) => {
    rsp.json(this.booksService.getAllBooks());
  }

}

This does have some performance implications, as the function will be created in the constructor, but if you are just going to create an arrow function on each call anyway it should be worse.

Upvotes: 1

Related Questions