113

I'm trying to make a simple API using typescript and NodeJS but when I run my code I get this error

"This module is declared with using 'export =', and can only be used with a default import when using the 'esModuleInterop' flag."

This is my code: package.json

    {
  "name": "API-Proyecto",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^4.17.1",
    "jsonwebtoken": "^8.5.1"
  },
  "devDependencies": {
    "@types/cors": "^2.8.6",
    "@types/express": "^4.17.6",
    "nodemon": "^2.0.4"
  }
}

Index.ts

    import express from 'express';
import { Request, Response }  from 'express';
import cors from 'cors';

const app = express();

app.use(express.urlencoded({extended: true}));
app.use(express.json);
app.use(cors({origin: true, credentials: true}));

app.get('/api/auth/testing', (req: Request, res: Response) =>{
    res.status(200).json({
        ok : true,
        msg : 'hi from my method'
    });
});

app.listen(3000, () => {console.log('Server running on 3000' )});

tsconfig.json

    {
  "compilerOptions": {
    "target": "es6",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
    "outDir": "./dist",                        /* Redirect output structure to the directory. */
    "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
  }
}
Antonio Labra
  • 1,694
  • 2
  • 12
  • 21

14 Answers14

169

Your code is perfectly fine.

Fix

When you make changes to tsconfig, sometimes you need to restart your IDE or Code Editor

Cavdy
  • 598
  • 8
  • 15
basarat
  • 261,912
  • 58
  • 460
  • 511
101

Use:

import * as express from 'express';
Ayrton Everton
  • 1,049
  • 1
  • 7
  • 6
  • 1
    I had a similar issue for momentjs in VSCode and your approach resolved my case. – Utku A. Dec 20 '21 at 18:43
  • This raised a tsserver error on `express()`: `This expression is not callable. Type 'typeof e' has no call signatures. (tsserver 2349)` – manuch100 Jun 20 '23 at 09:46
  • Maybe you're using a version of the `express` package that doesn't return a function by default, so I recommend either looking in the documentation or trying to find it in their project implementation or doing a debug to see everything that is exported by `express`, because there may be some version that needs to call a function inside the object, which would be something like `express.function()`. – Ayrton Everton Jun 21 '23 at 14:25
29

My problem was that I tried to run tsc as tsc -w index.ts.

However, as said here https://stackoverflow.com/a/33244030/5711655 if you run tsc with a specified input file, it won't use the tsconfig.json in your project directory! So in my case I had to use tsc -w.

jeti
  • 1,650
  • 1
  • 19
  • 28
  • 1
    That is so annoying that tsc ignores tsconfig.json when called with a specific file argument. – hlovdal Apr 25 '23 at 12:25
17

I fixed similar mistake for yourself. I use project (vite + vue 3 + ts)

  1. added on tsconfig.json->compilerOptions + "moduleResolution": "node".
  2. import moment from "moment" to import * as moment from "moment";

UPD:- and add this setting,

"allowSyntheticDefaultImports": true

and then I can use, import moment from "moment";

Anil Nivargi
  • 1,473
  • 3
  • 27
  • 34
LOC
  • 171
  • 1
  • 5
12

I was able to solve it by setting the "esModuleInterop" property to true inside the "compilerOptions" object in the tsconfig.json file.

{
  "compilerOptions": {
    "esModuleInterop": true,
    ...
  },
}

atleugim
  • 121
  • 1
  • 5
7

Don't forget to set "moduleResolution": "node" in the tsconfig.json if you are using node.

glennsl
  • 28,186
  • 12
  • 57
  • 75
TommyTomato
  • 123
  • 2
  • 10
6

when working with Ts you you need to add a flag on your tsconfig.json file that allow Synthetic Imports as so:

  • open tsconfig.json
  • add: { "compilerOptions": { "jsx": "react", "module": "es6", "target": "es6", "moduleResolution": "node", "allowSyntheticDefaultImports": true } }

Hope it helps. Cheers!

1

I was wondering a lot but a friend helped me:

  1. You need to create a command inside of "scripts" part on package.json

Package.json

{
  "name": "api-proyecto",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    **"build-dev": "tsc -w"**
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@types/cors": "^2.8.6",
    "@types/express": "^4.17.6"
  },
  "dependencies": {
    "cors": "^2.8.5",
    "express": "^4.17.1"
  }
}
  1. To run your script you need to type the following line

    npm i run build-dev (because it's the name of our command)

  2. Finally in another powershell launch node normally. For Example:

    node .\dist\index.js

Antonio Labra
  • 1,694
  • 2
  • 12
  • 21
1

FWIW, I found that switching from

import * as blah from 'blah-lib';

To

const blah = require('blah-lib');

Fixed the issue at compile time.

Joseph Lust
  • 19,340
  • 7
  • 85
  • 83
1

I solved the problem by compiling the whole file instead of compiling individual files.

Just run the following command to compile the whole file in a go

npx tsc

This should solve your problem

citizen4
  • 41
  • 2
  • It works for me with conjunction with this answer: https://stackoverflow.com/a/74788007/7883681 – Tayan May 10 '23 at 23:21
0

After trying all of the above solutions to no avail, I stumbled upon a solution for my case. I don't know why this works but running tsc instead of tsc index.ts or tsc --watch index.ts compiled fine. This error makes no sense to me at all. If someone can enlighten me and other readers of this post, it would be greatly appreciated.

Bus42
  • 130
  • 6
  • This is already explained in an earlier answer to this question: https://stackoverflow.com/a/67619647/224639 – Nev Stokes Oct 18 '22 at 10:06
0

I tried everything on this thread and it didn't work. What finally did was swapping tsc for ts-node to compile typescript in the app.

For reference I had this problem in a rushjs monorepo which may have further confused tsc

stakolee
  • 893
  • 1
  • 7
  • 20
0

Just like @basarat said rightfully, restarting Typescript can fix this issue. I already included "esModuleInterop": true, in tsconfig.json. I want to add, that you can do this via the Intellij Footer as well. Click on your Typescript version there.

Thanks for the help.

Intellij Footer

0

I had the same issue with my vscode, the error keeps on popping even with changing the tsconfig.json.

The problem was that tsconfig.json was extending from expo/tsconfig.base and somehow vscode didn't detect it.

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "src/*": ["src/*"],
      "static/*": ["static/*"]
    }
  },
  "extends": "expo/tsconfig.base"
}

I just opened this expo/tsconfig.base with right click and then save it to make vscode aware of this.

Srounsroun
  • 237
  • 2
  • 4