node.jstypescriptnode.js-got

Must use import to load ES module: ...\node_modules\got\dist\source\index.js


There's dozens of other questions with basically the same title, but none of the answers seem to be relevant and just add to the confusion.

This is my tsconfig.json:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "lib": ["es2017", "es7", "es6", "dom"],
    "declaration": true,
    "outDir": "dist",
    "strict": true,
    "esModuleInterop": true
  },
  "exclude": [
    "node_modules",
    "dist"
  ]
}

This is what I typed:

import md5 from 'js-md5';
import got from 'got';
import { Design } from './Design';
...

This is my error:

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: C:\Users\...\node_modules\got\dist\source\index.js require() of ES modules is not supported.

What. I'm not using require, I'm using import. I haven't had this error on any other modules, so why is Got different (and why is nothing ever simple)?

Why is this happening and how do I fix it?


As per @jsejcksn's answer, I tried changing my tsconfig.json to the following:

{
  "compilerOptions": {
    "target": "es6",
    "module": "esnext",
    "lib": ["es2017", "es7", "es6", "dom"],
    "declaration": true,
    "outDir": "dist",
    "strict": true,
    "esModuleInterop": true
  },
  "exclude": [
    "node_modules",
    "dist"
  ]
}

... and added "type": "module" to my package.json:

{
    "dependencies": {
        "body-parser": "^1.19.0",
        "express": "^4.17.1",
        "fs-extra": "^10.0.0",
        "got": "^12.0.1",
        "js-md5": "^0.7.3",
        "moment": "^2.29.1",
        "semver": "^7.3.5",
        "typescript": "^4.4.3",
        "uuid": "^8.3.2",
        "@types/node": "^16.9.2",
        "@types/express": "^4.17.13",
        "@types/fs-extra": "^9.0.13",
        "@types/semver": "^7.3.9",
        "@types/uuid": "^8.3.1",
        "@types/js-md5": "^0.4.3"
    },
    "type": "module"
}

But now I just get different errors :|

src/Logging.ts:1:20 - error TS2792: Cannot find module 'moment'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option?

1 import moment from 'moment';

src/SyncAPI.ts:2:17 - error TS2792: Cannot find module 'got'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option?

2 import got from 'got';


Solution

  • You have configured TypeScript to compile your modules to CommonJS format (your TSConfig option compilerOptions.module is set to "commonjs"). You'll need to set that option to an ESM-compatible setting (such as "esnext") so that the compiled JavaScript emitted by the TS compiler is in ESM format.

    In your package.json, you'll probably also need to set the "type" field to "module".


    Edit: To use npm packages by name as bare specifiers in your import statements, you'll also need to update your TSConfig compilerOptions.moduleResolution to "node". In your current config, you have included "dom" in the compilerOptions.lib array. "dom" is for environments with a DOM (which Node does not natively have), so that shouldn't be there. Instead, setting that array to ["es2017"] will include the others you have specified.


    Edit: In attempt to provide more direct guidance:

    {
      "compilerOptions": {
        "allowSyntheticDefaultImports": true,
        "declaration": true,
        "esModuleInterop": true,
        "lib": [
          "es2021"
        ],
        "module": "esnext",
        "moduleResolution": "node",
        "outDir": "dist",
        "strict": true,
        "target": "es2021"
      },
      "include": [
        "src/**/*"
      ]
    }
    
    {
      // ...
      "type": "module"
      // ...
    }
    

    You shouldn't have any trouble with import statement module system compatibility after that.