Search code examples
typescriptexpressnpmpackage.json

TypeScript: can only be default-imported using the 'esModuleInterop' flag


I've the following index.ts:

import { User } from "./datatypes"
import express from 'express';

 console.log("hello world")

This is my package.json:

{
  "name": "simple_app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "tsc index.ts && node index.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "dotenv": "^16.0.0",
    "express": "^4.17.3"
  },
  "devDependencies": {
    "@types/express": "^4.17.13",
    "@types/node": "^17.0.23",
    "ts-node": "^10.7.0",
    "typescript": "^4.6.3"
  }
}

And this is my tsconfig.json:

{
    "compilerOptions": {
      "module": "commonjs",
      "esModuleInterop": true,
      "resolveJsonModule": true,
      "target": "es6",
      "moduleResolution": "node",
      "sourceMap": true,
      "outDir": "dist"
    },
    "lib": ["es2015"]
  }

When I write npm run start, I obtain:

 Module '"/mnt/c/Users/raffa/Desktop/simple_app/node_modules/@types/express/index"' can only be default-imported using the 'esModuleInterop' flag

2 import express from 'express';
         ~~~~~~~

  node_modules/@types/express/index.d.ts:133:1
    133 export = e;
        ~~~~~~~~~~~
    This module is declared with using 'export =', and can only be used with a default import when using the 'esModuleInterop' flag.

How can I solve this problem?


Solution

  • If you call tsc from the command line with a specific file path, it will ignore your tsconfig.json

    Typescript docs (https://www.typescriptlang.org/docs/handbook/tsconfig-json.html):

    When input files are specified on the command line, tsconfig.json files are ignored.

    This means that the esModuleInterop part of tsconfig.json will have no effect if you call tsc index.ts.

    It's possible to work around it by using import * as express from 'express';, but there may be other issues arising from ignored TS configs.

    One problem with tsc -w && node index.js (from one of the comments) is that the -w will make it wait instead of terminating by itself, which means you won't get to the part after the "&&".
    So, you won't get to the node index.js part.
    (But at least this time, tsc doesn't get one specific file, therefore the config is not ignored)

    Also, in your config, the outDir is set to dist, so the compiled file will go there. So, you should use the following instead:
    tsc && node ./dist/index.js