Cannot use import statement outside a module using Express and Typescript, I'm deeply confused about modules

Viewed 5395

I'm trying to learn Typescript but I've gotten hung up on using modules, imports and exports while using Express. First, my code (I'll shorten irrelevant parts):

Full code https://github.com/coldblade2000/BannerServer

courses.js ( "/courses route handler for Express)

var express = require('express');
var router = express.Router();
const mongoose = require('mongoose')
const {CourseModel} = require('../MongoDB/models/models.ts')

const {Course} =  require('../model/Course.ts'); //<----ERROR HERE
//const {retrieveMultipleCourses} = require('../model/model.ts')

mongoose.connect('mongodb://localhost:27017/banner', {useNewUrlParser: true, useUnifiedTopology: true});
/* GET users listing. */
router.get('/', async function (req, res, next) {
    ...
});

function isEmpty(obj) {
    ...
}

module.exports = router;

Course.ts

import * as mongoose from 'mongoose' //<----ERROR HERE: SyntaxError: Cannot use import statement outside a module
// const mongoose = require('mongoose')
export interface Course{
    ...
}

export class CourseClass implements Course{
    ...
}


export interface Professor{
    ...
}
export interface Meeting {
    ...
}
export interface Days{
    ...
}

Error


> server@0.0.0 start C:\Users\diego\Desktop\BannerServer
> node bin/www.js && nodemon app.js

C:\Users\diego\Desktop\BannerServer\model\Course.ts:1
    import * as mongoose from 'mongoose'
    ^^^^^^

SyntaxError: Cannot use import statement outside a module
    at wrapSafe (internal/modules/cjs/loader.js:979:16)
    at Module._compile (internal/modules/cjs/loader.js:1027:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (C:\Users\diego\Desktop\BannerServer\routes\courses.js:6:19)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Module.require (internal/modules/cjs/loader.js:952:19)
    at require (internal/modules/cjs/helpers.js:88:18)
    at Object.<anonymous> (C:\Users\diego\Desktop\BannerServer\app.js:9:21)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)

Tsconfig.json

```{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "rootDir": "./",
    "outDir": "./build",
    "esModuleInterop": true,
    "strict": true
  }
}

package.json

{
  "name": "server",
  "version": "0.0.0",
  "private": true,
  "module": "CommonJS",
  "scripts": {
    "start": "node bin/www.js && nodemon app.js",
    "build": "tsc --project ./",
    "tsc": "tsc",
    "dev": "nodemon —exec babel-node app.js"
  },
  "dependencies": {
    "@typegoose/typegoose": "^7.4.1",
    "@types/node": "^14.14.1",
    "cookie-parser": "~1.4.4",
    "cors": "^2.8.5",
    "debug": "~2.6.9",
    "ejs": "~2.6.1",
    "express": "~4.16.1",
    "http-errors": "~1.6.3",
    "mongoose": "^5.10.4",
    "morgan": "~1.9.1"
  },
  "devDependencies": {
    "@babel/core": "^7.12.10",
    "@babel/node": "^7.12.10",
    "@babel/preset-env": "^7.12.11",
    "@types/mongoose": "^5.7.36",
    "nodemon": "^2.0.6",
    "ts-node": "^9.1.1",
    "typescript": "^4.1.3"
  }
}

So the problem I have is that I get SyntaxError: Cannot use import statement outside a module when I use import * as mongoose from 'mongoose' in Course.ts. I get the same error if I change const Course = require('../model/Course.ts'); in courses.js to import Course from ''.../model/Course.ts', but this time in the line I just changed. Even when I try to change Course.ts to use module.exports, the problem persists. I am at my wits end, so I require help. Since Express doesn't seem to like ES6 modules, I don't think I can just put "type:module" in package.json. I put in

2 Answers

TS file is not transpiled into JS in your build folder. so to make sure go to the file bath in build folder and you will see it still *.ts file

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "baseUrl": "./",
    "outDir": "./build",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "sourceMap": true,
    "incremental": true
  },
  "exclude": ["node_modules", "build"]
}

I managed to fix the issue. It was thanks to both @Hegazy and @Evert.

My main issue, as @Evert pointed out, I changed my "start" script to first compile using tsc, and also pointed node to point to /build/... instead of just /....

My current package.json

{
  "name": "server",
  "version": "0.0.0",
  "private": true,
  "module": "CommonJS",
  "scripts": {
    "start": "tsc && node build/bin/www.js && nodemon app.js",
    "build": "tsc --project ./",
    "tsc": "tsc"
  },
  "dependencies": {
    "@typegoose/typegoose": "^7.4.1",
    "@types/node": "^14.14.1",
    "cookie-parser": "~1.4.4",
    "cors": "^2.8.5",
    "debug": "~2.6.9",
    "ejs": "~2.6.1",
    "express": "~4.16.1",
    "http-errors": "~1.6.3",
    "mongoose": "^5.10.4",
    "morgan": "~1.9.1"
  },
  "devDependencies": {
    "@types/mongoose": "^5.7.36",
    "@typescript-eslint/eslint-plugin": "^4.11.0",
    "@typescript-eslint/parser": "^4.11.0",
    "eslint": "^7.16.0",
    "nodemon": "^2.0.6",
    "ts-node": "^9.1.1",
    "typescript": "^4.1.3"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "baseUrl": "./",
    "outDir": "./build",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "experimentalDecorators": true,
    "sourceMap": true,
    "allowJs": true,
    "incremental": true
  },
  "exclude": ["node_modules", "build"]
}
Related