How to Resolve "TypeError: X is not a constructor" in JavaScript
The TypeError: X is not a constructor is a common error in JavaScript that occurs when you try to use the new keyword with a value that is not a valid constructor. This typically happens when you mistake a regular object or an arrow function for a class or a constructor function.
This guide will explain what a constructor is in JavaScript and walk you through the common scenarios that trigger this error, including issues with arrow functions and ES module imports.
The Core Problem: What is a Constructor?
In JavaScript, a constructor is a special function that is used to create and initialize objects. The new keyword is what invokes this constructor.
Values that can be used as constructors include:
- Classes:
class MyClass { ... } - Constructor Functions:
function MyFunction() { ... }(a convention, usually starting with a capital letter)
Values that cannot be used as constructors include:
- Plain objects (
{}) - Primitive values (
123,'hello',true) - Arrow functions (
() => {}) - Most built-in methods (e.g.,
Promise.resolve)
The "is not a constructor" error occurs when you try to use new on any of the items in the "cannot" list.
Cause 1 (Most Common): Using new on a Plain Object or Primitive
This is the most straightforward cause of the error. The code is attempting to instantiate a value that is not a class or a constructor function.
Example of problem:
let myObject = { name: 'Alice' };
let myNumber = 42;
// ⛔️ TypeError: myObject is not a constructor
let instance1 = new myObject();
// ⛔️ TypeError: myNumber is not a constructor
let instance2 = new myNumber();
The new keyword is being used incorrectly on an object literal and a number.
Solution: only use the new keyword with valid constructors.
// ✅ Correct: Using a class as a constructor.
class Person {
constructor(name) {
this.name = name;
}
}
let personInstance = new Person('Alice');
// ✅ Correct: Using a traditional function as a constructor.
function Car(make) {
this.make = make;
}
let carInstance = new Car('Toyota');
Cause 2: Using new on an Arrow Function
Arrow functions are syntactically different from traditional functions and cannot be used as constructors. They do not have their own this context in the same way, which is a requirement for a constructor.
Example of problem:
// Problem: Arrow functions cannot be constructors.
let Animal = (name) => {
this.name = name;
};
// ⛔️ TypeError: Animal is not a constructor
let myAnimal = new Animal('Dog');
Solution: to create a constructor, you must use either a class (recommended) or a traditional function declaration.
// ✅ Correct: Use a class or a function.
class Animal {
constructor(name) {
this.name = name;
}
}
let myAnimal = new Animal('Dog');
Cause 3: A Mismatch Between Default and Named Imports
This is a very common source of this error when working with ES Modules. It happens when you import a module incorrectly, and the variable you think is a class is actually undefined or an object containing the exports.
Problem: imagine you have a file that exports a class as the default export.
Person.js:
export default class Person {
// ...
}
Now, if you try to import it using the named import syntax (with curly braces), you will get the error.
main.js:
// ⛔️ Incorrect: Using a named import for a default export.
import { Person } from './Person.js';
// At this point, `Person` is `undefined`.
// The error will be "TypeError: Person is not a constructor"
// (or "Cannot read properties of undefined").
let p = new Person();
This fails because the module does not have a named export called Person.
Solution: use the correct import syntax for the export type.
- Default exports are imported without curly braces.
- Named exports are imported with curly braces.
// ✅ Correct: Use a default import for a default export.
import Person from './Person.js';
let p = new Person();
Conclusion
The TypeError: X is not a constructor is a clear signal that you are misusing the new keyword.
When you see this error, check the following:
- Are you trying to use
newon a plain object or a primitive value? You can only usenewon classes and constructor functions. - Are you trying to use
newon an arrow function? This is not allowed; convert it to aclassor afunction. - Are you working with ES Modules? Double-check that you are not mixing up your default and named imports. An incorrect import can lead to your variable being
undefined, which is not a constructor.