Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'This' is undefined in typescript even using arrow func in a promise

When I receive the 'catch' callback, 'this' is undefined, even using arrow funcitions. Any ideas?

private all(req: Request, res: Response): void {
    EntityRepository.getRepositoty(req.params.etName).then(repo => {

        ...

    }).catch((err) => {
        this.handleError(res, err); // here I get undefined.
    });
}

how the all func is called.

It's called based on a Express route.

Added mathod bind as @jfriend00 suggested.

constructor() {
    // Connect to database.
    DataAccess.connect();

    // Starts configuring routes for api
    this.router = Router();

    // Bad request due to absence of entity type.
    this.router.get("/", (req, res) => {
        res.statusCode = 400;
        res.statusMessage = SysMsgs.error.noEntityTypeSpecified.message;
        res.send();
    });

    // Added method 'bind'.
    this.router.get(this.routeBase, this.all.bind(this));
    this.router.get(this.routeBase + "/:id", this.findOne.bind(this));
}
like image 690
Leandro Avatar asked Nov 28 '25 11:11

Leandro


1 Answers

With arrow functions, this will retain the value it had in the scope prior to the arrow function call. In your case, that means it will have whatever value this was at the beginning of your all function. So, that value of this depends upon how the all function is called.

And, based on your this.router.get() where you specify this.all as the callback, that means that this inside of all will be set to whatever Express sets it to when it calls that callback. And, that is undefined.

You can fix your issue by using .bind().

 this.router.get(this.routeBase, this.all.bind(this));

That will assure that the appropriate this is set when .all() runs. And, then your arrow function inside of all() will use that value of this.

Note: you will need to use .bind() for any method you are passing as a callback where you expect this to be the object inside the callback. When you pass something like this.all, the value of this is lost and only a reference to the method is passed. The caller then calls that method as a normal function with no object binding. You use .bind() to take control of that yourself. .bind() essentially creates a little stub function that reattaches the appropriate this pointer by calling your method using it.


You could also make your own wrapper arrow function for it:

 this.router.get(this.routeBase, (req, res) => this.all(req, res));

which as Saravana points out will retain TypeScript type checking.

like image 86
jfriend00 Avatar answered Dec 01 '25 00:12

jfriend00