15

In my nodejs, I have a small mongoose module which exports the model (User). When I require the module without using destructuring assignment and I create the new instance of the model using new operator, I get the error that the model is not a function. But if i use the destructuring assignment when I require the model, everything works fine. Not able to understand why.

User.js exports the model

const mongoose = require('mongoose');

exports.User = mongoose.model('User', {
    email:{
        type: String,
        trim: true,
        minlength: 1,
        reuqired: true
    }
});

Below code throws error if I dont use destructuring operator on line 2:
server.js

const mongoose = require('../DB/mongoose');
const User = require('../Models/User');

console.log(typeof(User));

let user = new User({
    email: "sdfdsf"
});

server.js throws the below error:

let user = new User({
           ^

TypeError: User is not a constructor
    at Object.<anonymous> (F:\javascript\nodePractice\ToDoApp\server\server.js:6:12)
    at Module._compile (internal/modules/cjs/loader.js:678:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
    at Module.load (internal/modules/cjs/loader.js:589:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:528:12)
    at Function.Module._load (internal/modules/cjs/loader.js:520:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:719:10)
    at startup (internal/bootstrap/node.js:228:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:576:3)

But If I use a destructuring assignment on line 2, it works all fine. server.js:

const mongoose = require('../DB/mongoose');
const {User} = require('../Models/User');

console.log(typeof(User));

let user = new User({
    email: "sdfdsf"
});
Luca Kiebel
  • 9,790
  • 7
  • 29
  • 44
kumarmo2
  • 1,381
  • 1
  • 20
  • 35
  • 1
    Of course it does, those two are not equivalent? – Bergi May 27 '18 at 16:24
  • Yeah... you're assigning an object that contains a `User` property to your `User` variable in `server.js` in the first case. – devius May 27 '18 at 16:27
  • 1
    This may help: [What do “module.exports” and “exports.methods” mean in NodeJS / Express?](https://stackoverflow.com/questions/6116960/what-do-module-exports-and-exports-methods-mean-in-nodejs-express) – Jonathan Lonowski May 27 '18 at 16:28

2 Answers2

21
const {User} = require('../Models/User');

is equivalent to

const User = require('../Models/User').User;
//                                    ^^^^^

The module object that require() returns (the exports object that your module filled) does have a .User property. If you don't access that but try to use the module object as a constructor, it throws.

To be explicit, you might want to use

const userModule = require('../Models/User');

console.log(typeof userModule);
console.log(typeof userModule.User);

let user = new userModule.User({
    email: "sdfdsf"
});

Alternatively, if you insist on doing const User = require('../Models/User');, you can also make the constructor function the exported object by overwriting module.exports instead of creating a property on it:

const mongoose = require('mongoose');

module.exports = mongoose.model('User', {
    …
});
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
2

You are exporting an object that has a property called "User" that hosts the model. When importing it you need to specify what part of the file you want to import, or you need to later specify what property you want to use. You can still use

const User = require('../Models/User');

But you will need to call User.User, accessing exports.User later on:

let user = new User.User({ //call exports.User from User model file
    email: "sdfdsf"
});
Luca Kiebel
  • 9,790
  • 7
  • 29
  • 44