Last updated: Feb 29, 2024
Reading timeยท3 min

The 'instanceof' error "only refers to a type, but is being used as a value
here" occurs when we try to use the instanceof operator with a type instead of
a value.
To solve the error, create a class instead, or simply use a user-defined type guard.

Here is an example of how the error occurs.
interface Employee { name: string; salary: number; } let emp: Employee; // โ๏ธ 'Employee' only refers to a type, but is being used as a value here.ts(2693) if (emp instanceof Employee) { console.log(emp.salary); }

The error was caused because we used the instanceof operator with a type instead of a value.
instanceof operator returns a boolean value indicating whether the prototype property of the constructor appears in the prototype chain of the object.instanceof with a class insteadOne way to solve the error is to use a class instead of an interface.
class Employee { constructor(public name: string, public salary: number) { this.name = name; this.salary = salary; } } const emp = new Employee('Bobby Hadz', 100); if (emp instanceof Employee) { // ๐๏ธ this runs console.log('โ is instance of Employee'); } console.log(emp instanceof Employee); // ๐๏ธ true

The emp object was created using the Employee class, so it is an instance of
the class.
You can also set class properties if you don't intend to take parameters when instantiating the class.
class Employee { name = ''; salary = 0; tasks: string[] = []; } const emp = new Employee(); emp.name = 'Bobby Hadz'; emp.salary = 100; emp.tasks.push('test'); if (emp instanceof Employee) { // ๐๏ธ this runs console.log('โ is instance of Employee'); } console.log(emp instanceof Employee); // ๐๏ธ true

However, you can have an object that satisfies the type but isn't an instance of the class because it wasn't created using the specific class.
class Employee { constructor(public name: string, public salary: number) { this.name = name; this.salary = salary; } } // ๐๏ธ Correct type, but not an instance const emp2: Employee = { name: 'Bobby Hadz', salary: 200, }; console.log(emp2 instanceof Employee); // ๐๏ธ false const emp = new Employee('Tom', 100); console.log(emp instanceof Employee); // ๐๏ธ true
The emp2 variable is not an instance of the Employee class, even though it
satisfies the type. The reason is that it wasn't created using the class.
instanceofIf you need to test if a specific object correctly implements a type, use a user-defined type guard.
interface Employee { id: number; name: string; salary: number; } function isAnEmployee(obj: any): obj is Employee { return 'id' in obj && 'name' in obj && 'salary' in obj; } const emp: Employee = { id: 3, name: 'Bobby Hadz', salary: 300, }; console.log(isAnEmployee(emp)); // ๐๏ธ true console.log(isAnEmployee({ id: 1 })); // ๐๏ธ false if (isAnEmployee(emp)) { // ๐๏ธ TypeScript knows that emp is type Employee console.log(emp.id); // ๐๏ธ 3 console.log(emp.name); // ๐๏ธ "Bobby Hadz" console.log(emp.salary); // ๐๏ธ 300 }

We used a user-defined type guard to check if an object implements an interface.
obj is Employee syntax is a type predicate where obj must be the name of the parameter the function takes.If the isAnEmployee function returns true, TypeScript knows that the passed
in value is of type Employee and allows us to access all properties and
methods on the specific interface.
The example above simply checks if the passed-in object contains the id,
name and salary properties.
This can get pretty verbose if your interface has many properties.
type property to the interfaceAn alternative approach is to
add a type property to the interface,
for which you check instead.
interface Employee { id: number; name: string; salary: number; type: 'Employee'; // ๐๏ธ add type property } function isAnEmployee(obj: any): obj is Employee { // ๐๏ธ check for type property return 'type' in obj && obj.type === 'Employee'; } const emp: Employee = { id: 3, name: 'Bobby Hadz', salary: 300, type: 'Employee', }; console.log(isAnEmployee(emp)); // ๐๏ธ true console.log(isAnEmployee({ id: 1 })); // ๐๏ธ false if (isAnEmployee(emp)) { console.log(emp.id); // ๐๏ธ 3 console.log(emp.name); // ๐๏ธ "Bobby Hadz" console.log(emp.salary); // ๐๏ธ 300 console.log(emp.type); // ๐๏ธ "Employee" }
The Employee interface has a type property with the string literal value of
Employee. This means that all objects that have a type of Employee will have
this property.
In our function, all we have to do is check if the passed-in object has a type
property that's equal to Employee.
You can learn more about the related topics by checking out the following tutorials: