error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'HTMLButtonElement'. is reported when a function says what this must be, through a @this tag or a this parameter in its type, and a call gives it something else. A plain call, onSave(event), gives this the type void.
In JavaScript the same mistake surfaces at run time as TypeError: Cannot set properties of undefined in strict-mode code, or as a write to the global object in sloppy scripts.
At a glance
| Code | TS2684 |
|---|---|
| Message | The 'this' context of type '{0}' is not assignable to method's 'this' of type '{1}'. |
| TypeScript's category | error |
| Listed under | Types do not match |
| Turned on by | No option: every checked file reports it |
| In .js files | Reported when the file is checked: checkJs in jsconfig.json, or // @ts-check at the top of the file |
The message is TypeScript's own text from its diagnostic messages file (Apache-2.0); {0} and {1} are filled in by tsc for each error.
What it looks like
/**
* @this {HTMLButtonElement}
* @param {MouseEvent} event
*/
function onSave(event) {
this.disabled = true;
console.log(event.type);
}
onSave(new MouseEvent("click"));error TS2684: The 'this' context of type 'void' is not assignable to method's 'this' of type 'HTMLButtonElement'.
export { onSave };jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["**/*.js"]
} What causes it
- An event handler or method that uses
thisis called directly instead of by the code that setsthis(addEventListener,call,apply). - A method is taken off its object (
const save = form.save) and called on its own.
How to fix it
Call it the way it expects
Pass the function to whatever sets this (addEventListener sets it to the element), or supply it yourself with call, apply or bind.
/**
* @this {HTMLButtonElement}
* @param {MouseEvent} event
*/
function onSave(event) {
this.disabled = true;
console.log(event.type);
}
const button = document.createElement("button");
button.addEventListener("click", onSave);
onSave.call(button, new MouseEvent("click"));
export { onSave };jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["**/*.js"]
} Or stop relying on this
A handler can read the element from event.currentTarget instead, and a method can be bound once in the constructor or written as an arrow function field. Then it can be called any way, and the @this tag goes.
Gotchas
- Passing a
@thisfunction toaddEventListeneron an element of another type was not reported in this site's tests: the listener overloads accept it. The check covers direct calls. @thison an arrow function is a different error (TS2730), because arrows takethisfrom where they are written.
Sources
- More on Functions: declaring this · TypeScript handbook
- JSDoc Reference: @this · TypeScript handbook
- diagnosticMessages.json (TypeScript 5.9.3) · TypeScript on GitHub
Last reviewed 21 October 2026.