Last updated: Feb 29, 2024
Reading timeยท2 min
The error "An outer value of 'this' is shadowed by this container" occurs when
we use named functions instead of arrow functions and shadow the value of
this
.
To solve the error, use an arrow function because they use this
of the
enclosing scope (the class instance).
Here are 2 examples of how the error occurs.
class Employee { constructor(public salary: number) { this.salary = salary; } increaseSalary = function () { // 'this' implicitly has type 'any' because it does not have a type annotation.ts(2683) // โ๏ธ index.ts(6, 20): An outer value of 'this' is shadowed by this container. this.salary += 100; return this.salary; }; // ------------------------------------------------ incSal() { // ๐๏ธ using this in nested function function nested() { console.log(this); // ๐๏ธ undefined // โ๏ธ index.ts(14, 14): An outer value of 'this' is shadowed by this container. this.salary += 100; return this.salary; } nested(); } } const emp = new Employee(100);
We used a function expression to declare the increaseSalary
method and
TypeScript isn't happy about our use of the this
keyword inside the function
expression.
The second error is much more common - we have a nested function inside of a method.
The nested function uses the this
keyword, however, it has a value of
undefined
and shadows the this
keyword inside of the incSal
method which
actually refers to the class instance.
To get around this, convert your named functions to an arrow function.
class Employee { constructor(public salary: number) { this.salary = salary; } increaseSalary = () => { // ๐๏ธ `this` refers to class instance here this.salary += 100; return this.salary; }; // ------------------------------------------------ incSal = () => { // ๐๏ธ this refers to class instance here const nested = () => { // ๐๏ธ this refers to class instance here this.salary += 100; console.log(this.salary); return this.salary; }; nested(); return this.salary; }; } const emp = new Employee(100); console.log(emp.increaseSalary()); // ๐๏ธ 200 console.log(emp.incSal()); // ๐๏ธ 300
We used arrow functions instead of named functions when declaring our class methods.
this
of the enclosing scope. In other words, the this
keyword in a method that was declared using an arrow function refers to the class instance.This is the modern and less confusing way to deal with the this
keyword in
classes.
this
keyword is shadowed (overridden in the scope).There are other ways to get around it, e.g. by using the bind
method, however
arrow functions enable us to not think about the implementation detail of how
the this
keyword works.
Using arrow functions for class methods also makes our code more readable and direct.