Opilite Elix
Opilite Elix

Reputation: 30

Javascript class can’t construct (in Node.Js). Getting TypeError: x is not a constructor

I was playing around with JavaScript classes in Node.Js and tried out a Rectangle example class. But whenever I run this code from my index.js file:

const Rectangle = require('./Rectangle.js');

const myRectangle = new Rectangle(5,5,'1');

console.log(myRectangle.id);

I get this error: TypeError: Rectangle is not a constructor

This is the directory tree:

/home_folder
————> index.js
————> Rectangle.js

And this is the code in Rectangle.js file:

class Rectangle{
  height;
  width;
  identificator;
  area;
  perimeter;
  
  constructor(h, w, id, non_verbose = true){
    this.height = h;
    this.width = w;
    this.identificator = id;
    if(non-verbose == true){
      console.log('construction of ' + id+ ' done!');
    }
  }
  
  area(m = 1){
    this.area = this.height * this.width;
    if(m == 0){
      console.log(this.area);
    }else{
      return this.area;
    }
  }
  
}

The result I was excepting was something like this:

construction of rect1 done!
rect1

But the actual result is this:

TypeError: Rectangle is not a constructor.

I googled for solving but found nothing relevant.

Upvotes: 0

Views: 1018

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074238

You aren't exporting anything in Rectangle.js. You'd need:

module.exports = Rectangle;

...at the end if you want to make it the default export (which is how you're trying to import it). That replaces the default value of module.exports (which is {}) with your Rectangle function.


Side note: I strongly recommend using ESM in new projects (and using named exports), not the legacy CommonJS stuff. To do that in this case, you'd:

  1. Add "type": "module" to your package.json file.
  2. Add export in front of class Rectangle to export it as a named export.
  3. Change const Rectangle = require('./Rectangle.js'); to import { Rectangle } from "./Rectangle.js";

Here's a full example —

package.json (of course, you'll have other things in here, but just to show the type setting):

{
    "type": "module"
}

index.js:

import { Rectangle } from "./Rectangle.js";

const myRectangle = new Rectangle(5, 5, "1");

console.log(myRectangle.id);

Rectangle.js (I've removed some unnecessary things — no need for area to be a property — and fixed a couple of typo-level errors):

export class Rectangle {
    height;
    width;
    id; // Changed from `identificator` to match your usage in `index.js`

    constructor(h, w, id, non_verbose = true) {
        this.height = h;
        this.width = w;
        this.id = id;
        if (non_verbose) { // No reason for `== true` here
            console.log("construction of " + id + " done!");
        }
    }

    area(m = 1) {
        // No need to write this to a property as far as I can tell
        const area = this.height * this.width;
        if (m == 0) {
            console.log(area);
        } else {
            return area;
        }
    }
}

If you'd been using ESM and named import syntax in index.js but you'd forgotten to export Rectangle in Rectangle.js, you'd have gotten a nice clear error (rather than an unexpected value for Rectangle as you did with CommonJS):

SyntaxError: The requested module './Rectangle.js' does not provide an export named 'Rectangle'.

More about ESM here on MDN. I also go into ESM in depth in my recent book JavaScript: The New Toys in Chapter 13.

Upvotes: 4

Related Questions