19

New to Node and Typescript. I am getting an error that mongoose.connect is not a function when I run tsc.

I have the following code:

import express = require('express');
import * as mongoose from "mongoose";

/** Routes for the app */
import apiUserRouter from "./api/user"

class App{

   public express :express.Application


    constructor() {
        this.express = express()
        this.setupDb();
    }

    private setupDb() : void {
        var mongoDb = 'mongodb://127.0.0.1/my_database';
        mongoose.connect(mongoDb);
        var db = mongoose.connection;
        db.on('error', console.error.bind(console, 'MongoDB Connection error'));
    }
}

If I change

import * as mongoose from "mongoose"

to

import mongoose = require('mongoose');

Then everything works fine.

I have run the following npm command for types as my understanding is that this should have fixed the issue.

npm install @types/mongoose --save

Edit: Adding my packages.json

{
    "name": "nodejs-ts-test2",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "author": "",
    "license": "ISC",
    "devDependencies": {
        "@types/express": "^4.11.1",
        "@types/mongoose": "^5.0.3",
        "typescript": "^2.7.2"
    },
    "dependencies": {
        "express": "^4.16.2",
        "mongoose": "^5.0.7"
    }
}

and tsconfig.json:

{
    "compilerOptions": {
        "target": "es2015",
        "module": "commonjs",
        "outDir": "dist",
        "strict": true,
        "noImplicitAny": false,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true
    }
}

6 Answers 6

13

Since you didn't share your package.json or tsconfig, it was not possible to say where the error might be. So I created new project for the code you have shared such that the error does not occur. Compare the files that I am sharing with the ones you have to narrow down your problem.

The package.json

{
  "name": "mong_type",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/express": "^4.11.1",
    "@types/mongoose": "^5.0.3",
    "typescript": "^2.7.2"
  },
  "dependencies": {
    "express": "^4.16.2",
    "mongoose": "^5.0.7"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "es2015",
    "module": "commonjs",
    "outDir": "./dist",
    "strict": true,
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true
  },
  "include": ["src"]
}

src/app.ts

import express from "express";
import mongoose from "mongoose";

class App {
  public express: express.Application;

  constructor() {
    this.express = express();
    this.setupDb();
  }

  private setupDb(): void {
    var mongoDb = "mongodb://127.0.0.1/my_database";
    mongoose.connect(mongoDb);
    var db = mongoose.connection;
    db.on("error", console.error.bind(console, "MongoDB Connection error"));
  }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you for your help so far, it appears the express import now works. But the mongoose one still doesn't. When I run nodemon I get the following error: "mongoose.connect" is not a function.
Hey Chuck, Yeah sorry I didn't test that. I've updated the code to import mongoose so that you don't get that error.
Thank you for that. I will award the answer, however, why does 'import * as mongoose from "mongoose"' not work? It works on other pages I have in my project.
That's because I've used the rule "esModuleInterop": true in the tsconfig. If you remove that rule, you'll be able to import both express and mongoose using "import *" syntax.
5

This:

import mongoose from 'mongoose'

worked for me after running:

npm install mongoose @types/mongoose --save

Way more detailed explanation on why this works, here.

1 Comment

FYI deprecated @types/[email protected]: Mongoose publishes its own types, so you do not need to install this package.
2

The solution to this problem is to comment the below line in your tsconfig.json file found in your project's base directory, just comment this damn line

"esModuleInterop":true

Comments

1

This issue got fixed for me after adding "moduleResolution":"Node" to the tsconfig.json

My tsconfig.json

{
    "compilerOptions": {
      "target": "es2015",                          
      "module": "es6",
      "checkJs":true,                                 
      "allowJs": true,
      "outDir": "build",                          
      "rootDir": "src",
      "strict": true,         
      "noImplicitAny": false,
      "esModuleInterop": true,
      "allowSyntheticDefaultImports": true,
      "moduleResolution":"Node"
    }
  }

Comments

0

I got it working,

Try

import express from 'express'
const app = express()
import mongoose from 'mongoose'

Its a mix up of code...

some prove of concept.

https://bobbyhadz.com/blog/javascript-to-load-es-module-set-type-module-in-package-json

Comments

0

Cannot get it working. esModuleInterop and allowSyntheticDefaultImports dont seem to change anything. It works with

const mongoose = require('mongoose');

but not with ES6 like this

import mongoose from 'mongoose'

or this

import * as mongoose from 'mongoose'

tsconfig.json

{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "node",
    "importHelpers": true,
    "jsx": "preserve",
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "sourceMap": true,
    "baseUrl": "./",
    "strict": true,
    "paths": {},
    "allowSyntheticDefaultImports": true,
    "skipLibCheck": true
  },
  "include": ["src"],
  "references": [
    { "path": "./tsconfig.node.json" }
  ]
}
{
  "name": "electron-vue-vite",
  "version": "2.0.0",
  "main": "dist-electron/main/index.js",
  "description": "Really simple Electron + Vue + Vite boilerplate.",
  "author": "草鞋没号 <[email protected]>",
  "license": "MIT",
  "private": true,
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc --noEmit && vite build && electron-builder"
  },
  "engines": {
    "node": "^14.18.0 || >=16.0.0"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^3.1.2",
    "@vue/devtools": "^6.4.5",
    "electron": "^22.0.0",
    "electron-builder": "^22.10.3",
    "typescript": "^4.8.4",
    "vite": "^3.2.2",
    "vite-plugin-electron": "^0.10.4",
    "vite-plugin-electron-renderer": "^0.11.3",
    "vue": "^3.2.40",
    "vue-router": "^4.1.6",
    "vue-tsc": "^1.0.9"
  },
  "debug": {
    "env": {
      "VITE_DEV_SERVER_URL": "http://127.0.0.1:3344"
    }
  },
  "keywords": [
    "electron",
    "rollup",
    "vite",
    "vue3",
    "vue"
  ],
  "dependencies": {
    "apollo-server-express": "^3.11.1",
    "element-plus": "^2.2.27",
    "express": "^4.18.2",
    "graphql": "^16.6.0",
    "mongodb": "^4.13.0",
    "mongoose": "^6.8.3"
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.