node.jstypescript

Error ERR_REQUIRE_ESM require() of ES Module


I know this is a popular error but, I can't understand why I'm getting it at this point or maybe how to fix it. I have a TS project that I compile to JS and run. To build the project I simply run

tsc -p tsconfig.json

Then to run the project I run

node ./build/index.js

I have many modern packages like

  "dependencies": {
    "@fastify/cookie": "^8.3.0",
    "@fastify/cors": "^8.1.0",
    "@fastify/multipart": "^8.0.0",
    "@fastify/websocket": "^7.0.1",
    "@prisma/client": "^5.5.2",
    "fastify": "^4.6.0",
    "file-type": "^18.7.0",
    "mime-types": "^2.1.35",
    "nodemailer": "^6.8.0",
    "openai": "^3.1.0",
    "pg-error-enum": "^0.6.0",
    "ts-loader": "^9.4.2",
    "useragent": "^2.3.0"
  },
  "devDependencies": {
    "@types/jest": "^29.5.8",
    "@types/mime-types": "^2.1.1",
    "@types/node": "^18.7.20",
    "@types/nodemailer": "^6.4.6",
    "@types/useragent": "^2.3.1",
    "@types/ws": "^8.5.3",
    "jest": "^29.7.0",
    "nodemon": "^2.0.20",
    "prisma": "^5.5.2",
    "ts-jest": "^29.1.1",
    "typescript": "^5.2.2"
  },

And have been going without issues, until one day I added file-type

This package appears to be as modern as the rest. Yet I get this error as soon as I import it.

Error [ERR_REQUIRE_ESM]: require() of ES Module C:\xx\node_modules\file-type\index.js from C:\xx\build\File.js not supported.
Instead change the require of index.js in C:\xx\build\File.js to a dynamic import() which is available in all CommonJS modules.

My ts config file is as such

{
  "compilerOptions": {
    "declaration": true
    "composite": true
    "declarationMap": true
    "target": "es2021"
    "module": "commonjs" 
    "rootDir": "./src" 
    "moduleResolution": "node" 
    "sourceMap": true,
    "outDir": "build",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "skipLibCheck": true
  },
  "ts-node": {
    "compilerOptions": {
      "module": "commonjs"
    }
  }
}

I've genuinely tried changing so many of these fields and also adding type: module to my main package.json, but everything I do just breaks something else.

It kind of seems to me that somehow, file-type is the first package I've added that uses import/export natively, while things like fastify seem to use require() in their actual source or maybe build code. Can I not support using both types of packages?


Solution

  • In order to fix this I had to do a few things

    1. Change my tsConfig.json module option from commonjs to es2022
    2. Change my tsConfig.json ts-node.compilerOptions.module to es2022
    3. Add tsc-alias because of the refusal of either Typescript or Node developers to support import { thing } from './myfile' without a .js extension like import { thing } from './myfile.js'.

    Note that I don't use a bundler, I just build with typescript, so #3 is not necessary if you use webpack.. probably.