Reputation: 45
In the typescript documentation the following example is given on how to use type for this usage inside a callback function. Can someone please help me to understand how the callback will work here?
interface DB {
filterUsers(filter: (this: User) => boolean): User[];
}
const db = getDB();
const admins = db.filterUsers(function (this: User) {
return this.admin;
});
Upvotes: 1
Views: 53
Reputation: 1074355
For methods and traditional functions (not arrow functions), this
is effectively a read-only parameter whose value is passed to the function by the code calling it. (More here.) When the function's code runs, this
is whatever the caller set it to (explicitly or implicitly).
The this
pseudo-parameter in TypeScript lets you tell TypeScript what type this
will have when the function is called. So the DB
interface's filterUsers
method is defined saying that this
will refer to a User
object when the callback is called.
You don't have to repeat it when you write the callback (though you can), TypeScript will infer it from the DB
interface's definition:
const db = getDB();
const admins = db.filterUsers(function() {
return this.admin;
// ^? −−−−− here, `this` has the type `User`
});
In a comment you've asked:
How the function will bound to an
User
instance here ?
Code in filterUsers
will ensure that when it calls the callback, it does so with this
set to a user. It might do that with either Function.prototype.call
or Function.prototype.apply
:
// Notional (not literal!) code for a `filterUsers` method:
filterUsers(callback: (this: User) => boolean): User[] {
const filtered = this.users.filter(user => callback.call(user));
// ^^^^^ ^
// |
// the value to use as `this` −−−−+
return filtered;
}
.call
and .apply
allow you to explicitly state what this
should be when calling a function.
It's probably worth noting that this would be an unfortunate way for DB
's filterUsers
to be defined. It would be much more convenient for users of the interface if the user were passed as a simple parameter (as with Array.prototype.filter
and such), not as this
. But it's a synthetic example in the documentation for explaining this syntax.
Upvotes: 3