Skip to content

Support for Clean Running of .ts ESM Entry Points with ts-node/esm #2158

@paullewallencom

Description

@paullewallencom

Environment Information

tsconfig.json settings:

{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"target": "ES2022",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"skipLibCheck": true
}
}

Summary of the Problem

When launching a TypeScript .ts ESM entry point directly using:

node --loader ts-node/esm run-mocha.ts

Node.js throws:

Error [ERR_REQUIRE_CYCLE_MODULE]: Cannot require() ES Module run-mocha.ts in a cycle

This happens even when all imports inside the .ts file are using await import() dynamically (no static imports), and the tsconfig.json uses "module": "NodeNext" and "moduleResolution": "NodeNext" correctly.

Steps to Reproduce

  1. Clone this reproduction repository:
    👉 https://github.com/paullewallencom/issue-0000

  2. Install dependencies:

npm install

  1. Run the test script:

npm run test

  1. Observe the cycle error crashing immediately.

What I Expected to Happen

  • I expected ts-node/esm to properly defer static analysis or execution such that .ts ESM entrypoints could be executed cleanly without needing a .mjs bootstrap workaround.
  • I expected dynamic await import('mocha') to avoid early cycle detection issues.

Actual Behavior

  • Node detects a require cycle in the .ts entrypoint itself, even when using ts-node/esm.
  • The only way to avoid the crash is to create a separate .mjs bootstrap file (e.g., run-mocha-bootstrap.mjs) and dynamically import the .ts file from there.

Notes

  • I understand that Node's ESM loader is strict by design, but it seems like ts-node could provide a cleaner or more automated approach for .ts ESM entrypoints.
  • I am happy to help contribute to documentation or potential enhancements if needed.
  • Thank you very much for maintaining ts-node — it’s an incredibly valuable tool for TypeScript developers!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions