5

So I have my module written as such

import mongoose from 'mongoose';

export class MyModule {
   constructor(){
       //do
   }

   create(str){
      mongoose.connect(str); //cannot find property 'connect' of undefined
   }

}

When using the import syntax, I get the cannot find property 'connect' of undefined error; it works as intended when using require.

Weirdly enough, importing individual properties via import syntax works as intended,

import { connect } from 'mongoose'

but I need access to the entire ORM for some other reasons.

Why is it like so? Am I doing something wrong? To be fair, I don't have much experience in ES6 module system, TypeScript and Node.js so I might be missing something here.


I'm running this on Node.js with NestJS, on a typescript file.

Abana Clara
  • 4,602
  • 3
  • 18
  • 31
  • Has it installed `mongoose` in the `node_modules`? was there any error in npm installation? – nivendha Aug 07 '19 at 06:24
  • 1
    To be clear, when you replace the first line of your code example with `const mongoose = require('mongoose');` it works? Are you executing this code with Node.js? – Patrick Hund Aug 07 '19 at 06:25
  • @nivendha Yea, I have it in my package.json already and it's also existing in the node_modules folder – Abana Clara Aug 07 '19 at 06:25
  • @PatrickHund Yes and yes, and I'm using NestJS as a framework – Abana Clara Aug 07 '19 at 06:26
  • Import syntax mandates the file extension so `import mongoose from 'mongoose.js'`. Also, you cannot mix and match import and require syntax. Commonjs (nodejs) modules **must** use `require` and cannot use `import`. ES6 modules **must** use `import` and cannot user `require`. There is a possibility of writing modules that export both but not all do (in fact most don't) – slebetman Aug 07 '19 at 06:32
  • 2
    ```import * as mongoose from 'mongoose';``` try this – Binit Ghetiya Aug 07 '19 at 06:34
  • The reason for this is that the ES standards committee, being mostly browser developers, have defined the behavior of ES6 module loading that is not compatible with nodejs old module system – slebetman Aug 07 '19 at 06:34
  • @slebetman `import mongoose from 'mongoose.js'` doesn't seem to work. – Abana Clara Aug 07 '19 at 06:42
  • @BinitGhetiya `import * as mongoose from 'mongoose';` works amazingly! I think I also found the problem upon using this. It seems like Mongoose does not have a default export as reported by VS Code after installing `@types/mongoose`, that being the case, doing `import mongoose` explicitly will not work. – Abana Clara Aug 07 '19 at 06:43
  • Are you using babel js for ES6 – Hamid Raza Noori Aug 07 '19 at 06:44
  • @HamidRazaNoori Either that or is a Typescript compiler thing – slebetman Aug 07 '19 at 06:46
  • @AbanaClara I have added answer please mark it correct Thanks :) – Binit Ghetiya Aug 07 '19 at 07:37

4 Answers4

8

There are total 2 syntex we can use here.

ES15 (NodeJS)

const mongoose = require('mongoose');

then use mongoose.connect

ES16 (import/export)

import * as mongoose from `mongoose`;

then use mongoose.connect

or

import {connect} from `mongoose`;

then use connect directly

Community
  • 1
  • 1
Binit Ghetiya
  • 1,919
  • 2
  • 21
  • 31
  • Unfortunately this does not work as an acceptable answer to my problem (those useful for future readers). I have personally written an answer with a decent explanation and mention your handle instead. – Abana Clara Aug 07 '19 at 07:52
  • @AbanaClara No worries :), hope you got your answer. – Binit Ghetiya Aug 07 '19 at 09:31
4

In your tsconfig.json file, you can set

"allowSyntheticDefaultImports": true,
"esModuleInterop": true

This will allow you to use the syntax

import mongoose from 'mongoose';
nerdy beast
  • 779
  • 5
  • 8
2

After installing @types/mongoose, VS Code reports that mongoose does not have a default export (all being named exports) that being the case, doing

import mongoose from `mongoose`

will not work. This also explains why getting individual properties instead works:

import { connect } from `mongoose`

As a workaround, thanks to @Binit Ghetiya who first mentioned it in this thread, you should do this instead:

import * as mongoose from `mongoose`

Which compiles every named export from Mongoose into the variable mongoose.

Abana Clara
  • 4,602
  • 3
  • 18
  • 31
0

Just change the import as follows:

import * as mongoose from 'mongoose';

Here is an example:

import * as mongoose from 'mongoose';

export class MyModule {

   constructor(){
       //do
   }

   create(str){
      mongoose.connect(str);
   }
}
  • Note that this is a Typescript specific syntax and breaks the ES6 standards. For now it works but in the future when Typescript re-aligns with ES6 this may break (or it may not, depends on what Microsoft wants to do with the language they invented). See: https://stackoverflow.com/questions/29596714/new-es6-syntax-for-importing-commonjs-amd-modules-i-e-import-foo-require – slebetman Aug 07 '19 at 06:54