Solvedts node ts-node fails when ES Modules are in the dependency graph in Node.js 13+

I basically detailed the issue in this comment: #155 (comment)

It's a chicken-and-egg-like problem:

  • If we use module: 'commonjs', then if any TS files import ES Modules (indirectly in their dependency graph), then Node throws an error because CommonJS modules can not import ES Modules.
  • If we change to module: 'esnext', then the errors from the previous point go away, but now the .js file that is loading ts-node and calling something like require('typescript-entry-point.ts') will have a similar issue, because the call to require('typescript-entry-point.ts') will try to load an ES Module.
  • Finally, if we convert the .js file into an ES Module, we can not convert require('typescript-entry-point.ts') into import 'typescript-entry-point.ts' because now ES Modules don't handle .ts extensions (at least not out of the box, and it seems the old require hooks don't operate on these new identifiers)

At the moment, I'm sort of stuck, because I have dependencies in my dependency tree that are ES Modules.

The only workaround I can think of is to compile everything to .js files (ES Modules) and avoid to use ts-node.

I wonder if a combination of allowJs and ignore so that it compiles JS files would help. I haven't tried that yet.

36 Answers

✔️Accepted Answer

It seems that ts-node fails to run with "module": "esnext" in the tsconfig.json and "type": "module" in the package.json with the following error:

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /Users/user/test-project/index.ts
    at Loader.defaultGetFormat [as _getFormat] (internal/modules/esm/get_format.js:71:15)
    at Loader.resolve (internal/modules/esm/loader.js:98:42)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at Loader.getModuleJob (internal/modules/esm/loader.js:188:29)
    at Loader.import (internal/modules/esm/loader.js:163:17)

Other Answers:

If anyone is coming to this issue like I did I was able to get TS working inside a project with "type": "module" through nodemon by adding a nodemon.json with this in it:

{
  "execMap": {
    "ts": "node --loader ts-node/esm"
  }
}

Essentially replacing the default "execMap" of "ts": "ts-node" … in case it matters my tsconfig.json like:

{
  "compilerOptions": {
    "module": "ESNext",
    "target": "ESNext",
    "moduleResolution": "node",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "isolatedModules": true,
    "noEmit": true,
    "strict": true,
    "lib": [
      "es2020"
    ]
  }
}

With that my "dev" script in package.json is just "nodemon src/index.ts" and it all seems to work!

Well, looks like @K-FOSS/TS-ESNode does work with Node 13.7. That's amazing. I'll get to work on porting this directly into ts-node hopefully sometime this weekend. Work has been busy, not enough time for personal coding.

same issues occurring right now

If you're still facing the issue with module ESNext, this saved my day:

If you must keep "module": "ESNext" for tsc, webpack, or another build tool, you can set an override for ts-node.

{
  "compilerOptions": {
    "module": "ESNext"
  },
  "ts-node": {
    "compilerOptions": {
      "module": "CommonJS"
    }
  }
}

Source: https://www.npmjs.com/package/ts-node?activeTab=readme#commonjs

More Issues: