kulshekhar / ts-jest

A Jest transformer with source map support that lets you use Jest to test projects written in TypeScript.
https://kulshekhar.github.io/ts-jest
MIT License
6.94k stars 452 forks source link

[Bug]: Using "module": "NodeNext" causes the error "SyntaxError: Cannot use import statement outside a module" #4464

Closed chrismeyers closed 2 months ago

chrismeyers commented 2 months ago

Version

29.2.1+

Steps to reproduce

  1. Clone https://github.com/chrismeyers/reproduce-tsjest-29.2.1-error-nodenext
  2. Run yarn test and see the error
  3. Change the version of ts-jest to the latest (currently 29.2.3), then run yarn test and see the error
  4. Change the version of ts-jest to 29.2.0, then run yarn test and tests should pass

Expected behavior

Tests should pass

Actual behavior

The test suite fails to run

Debug log

ts-jest.log

Additional context

Appears to be very similar to https://github.com/kulshekhar/ts-jest/issues/4439

Environment

System:
    OS: macOS 14.5
    CPU: (8) arm64 Apple M1 Pro
  Binaries:
    Node: 20.15.1 - ~/.nvm/versions/node/v20.15.1/bin/node
    Yarn: 1.22.22 - ~/.nvm/versions/node/v20.15.1/bin/yarn
    npm: 10.7.0 - ~/.nvm/versions/node/v20.15.1/bin/npm
    bun: 1.1.13 - ~/.bun/bin/bun
  npmPackages:
    jest: 29.7.0 => 29.7.0
ahnpnl commented 2 months ago

I think I know the issue. Since we allow the usage of Node16 and NodeNext, the code transpilation takes into account of type: module in package.json which results in compiled codes are in ESM format while your example runs with Jest in CJS mode.

There are 2 ways to workaround your issue:

Hi @SimenB @mrazauskas can Jest automatically pick up type: "module" in package.json to detect that it needs to run in ESM mode? From ts-jest side, we doesn't have the information of package.json so it's very hard for us to warn about "user should not use Node16/NodeNext with type: "module" in CJS mode"

chrismeyers commented 2 months ago

I can confirm that changing to "module": "ESNext" or "module": "CommonJS" fixes the error. I'm guessing NodeNext stopped working after https://github.com/kulshekhar/ts-jest/pull/4429?

For a bit more context, I'm using tshy which is fairly opinionated and generates code using NodeNext. Ideally this can go back to working like it did prior to 29.2.1 so that the tests and built code use the same module and moduleResolution settings, but at least there's a path forward.

ahnpnl commented 2 months ago

Actually before the fix, Node16 and NodeNext were ignored during code transpilation. The default module was always CommonJS when transpiling codes for Jest when it ran in CJS mode.

After the fix, we take into account of Node16 and NodeNext when transpiling codes. This results in the failed tests you saw. As TypeScript documentation states at https://www.typescriptlang.org/tsconfig/#node16nodenext

If we revert back, the support for these 2 module values won’t be possible. Ideally, Jest should be able to run in ESM mode when it sees type: module.

On a side note, I saw your example repo uses ESM preset but the script to run test is without --experimental-vm-modules which made Jest not able to run ESM codes.

I don’t think it’s possible for us to fix this issue. We highly depend on what Jest wants to accept.

chrismeyers commented 2 months ago

I see, this is all starting to make more sense. I didn't realize that the --experimental-vm-modules flag has to be provided to enable ESM mode in Jest and that ts-jest emitted CJS otherwise before these changes.

Updating the test script in my example to node --experimental-vm-modules ./node_modules/.bin/jest fixed the tests with no other changes to the tsconfig.json or jest.config.json.

I appreciate your time looking into this! I think it's okay to close this issue.

ahnpnl commented 2 months ago

Thanks!