Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Node16/NodeNext value for moduleResolution #4198

Open
alumni opened this issue Aug 25, 2023 · 23 comments · Fixed by #4429
Open

Support Node16/NodeNext value for moduleResolution #4198

alumni opened this issue Aug 25, 2023 · 23 comments · Fixed by #4429
Labels
🐛 Bug Confirmed Bug is confirmed

Comments

@alumni
Copy link

alumni commented Aug 25, 2023

Version

29.1.1

Steps to reproduce

I have a monorepo setup with multiple apps and libraries. One of the apps (the largest, the only one with isolatedModules: true) fails after updating to TS 5.2 with the following error: error TS5110: Option 'module' must be set to 'Node16' when option 'moduleResolution' is set to 'Node16'.

Currently using @tsconfig/node18/tsconfig.json for the monorepo base config, which contains the following:

{
    "module": "node16",
    "moduleResolution": "node16"
}

The module option is overridden by ts-jest:

  • returned 100 instead of node16: dist/legacy/config/config-set.js in _resolveTsConfig()
  • from 100 to 1: dist/legacy/compiler/ts-compiler.js in getCompiledOutput()

Expected behavior

I would expect that module is not changed.

Actual behavior

module is changed first to 100 and later to 1 (CommonJs)

Debug log

extracted info above

Additional context

No response

Environment

System:
    OS: Windows 10 10.0.19044
    CPU: (8) x64 Intel(R) Core(TM) i7-8665U CPU @ 1.90GHz
  Binaries:
    Node: 18.17.0 - ~\AppData\Local\fnm_multishells\16532_1692954691139\node.EXE
    Yarn: 1.22.19 - ~\AppData\Local\fnm_multishells\16532_1692954691139\yarn.CMD
    npm: 9.8.1 - ~\AppData\Local\fnm_multishells\16532_1692954691139\npm.CMD
    pnpm: 8.6.12 - ~\AppData\Local\fnm_multishells\16532_1692954691139\pnpm.CMD
  npmPackages:
    jest: ^29.6.4 => 29.6.4
@zapteryx
Copy link

getting this as well after updating to TS 5.2.2

@andrew-pledge-io
Copy link

andrew-pledge-io commented Aug 30, 2023

I have the same issue. As a temporary workaround I've set moduleResolution to classic in the ts-jest configuration:

module.exports = {
  transform: {
    '^.+\\.tsx?$': [
      'ts-jest',
      { tsconfig: { moduleResolution: "classic" } },
    ],
  },
};

@chentsulin
Copy link
Contributor

The code overrides module in getCompiledOutput():

if (
(this.configSet.babelJestTransformer || (!this.configSet.babelJestTransformer && options.supportsStaticESM)) &&
this.configSet.useESM
) {
moduleKind =
!moduleKind ||
(moduleKind &&
![this._ts.ModuleKind.ES2015, this._ts.ModuleKind.ES2020, this._ts.ModuleKind.ESNext].includes(moduleKind))
? this._ts.ModuleKind.ESNext
: moduleKind
// Make sure `esModuleInterop` and `allowSyntheticDefaultImports` true to support import CJS into ESM
esModuleInterop = true
allowSyntheticDefaultImports = true
} else {
moduleKind = this._ts.ModuleKind.CommonJS
}

@DavidRigglemanININ
Copy link

I'm running into this as well and it looks like it's been a month since the last comment. Is there a fix coming out anytime soon for this?

@erunion
Copy link

erunion commented Nov 1, 2023

This patch fixed this issue for our use-case of using @tsconfig/node16 with module: node16 and moduleResolution: node16:

--- ./node_modules/ts-jest/dist/legacy/compiler/ts-compiler.js	2023-11-01 13:05:20.000000000 -0700
+++ ./node_modules/ts-jest/dist/legacy/compiler/ts-compiler.fixed.js	2023-11-01 13:09:38.000000000 -0700
@@ -132,7 +132,7 @@
             allowSyntheticDefaultImports = true;
         }
         else {
-            moduleKind = this._ts.ModuleKind.CommonJS;
+            moduleKind = this._compilerOptions.module || this._ts.ModuleKind.CommonJS;
         }
         this._compilerOptions = __assign(__assign({}, this._compilerOptions), { allowSyntheticDefaultImports: allowSyntheticDefaultImports, esModuleInterop: esModuleInterop, module: moduleKind });
         if (this._languageService) {

It seems like ModuleKind.CommonJS is pretty hardwired throughout ts-jest though so I don't know if anything is being missed here but this at least lets us run our tests with modern resolutions.

@raczkerry
Copy link

I am experiencing this as well and @erunion 's patch is fixing this issue for me.

@darkbasic
Copy link

node16 works "fine" (at least with "noEmitOnError": false) for me even without the patch: #4207 (comment)

akheron added a commit to espoon-voltti/evaka that referenced this issue Nov 29, 2023
There's a bug in ts-jest that makes jest hang if tsconfig.json has a
certain combination of module and moduleResolution values. Fix this by
providing a differend tsconfig for ts-node.

See kulshekhar/ts-jest#4198 and
kulshekhar/ts-jest#4207.
akheron added a commit to espoon-voltti/evaka that referenced this issue Nov 29, 2023
There's a bug in ts-jest that makes jest hang if tsconfig.json has a
certain combination of module and moduleResolution values. Fix this by
providing a differend tsconfig for ts-node.

See kulshekhar/ts-jest#4198 and
kulshekhar/ts-jest#4207.
@patrickshipe
Copy link

I only encounter the issue if I do:

  transform: {
    '^.+\\.tsx?$': [
      'ts-jest',
      {
        isolatedModules: true,
      },
    ],
  },

If I leave out the isolatedModules option, it works just fine.

@lpc921
Copy link

lpc921 commented Dec 19, 2023

In addition to setting "noEmitOnError": false, I have to leave moduleResolution unspecified when "module": "Node16" or "module": "NodeNext" is set. If I set moduleResolution to Node16 or NodeNext, ts-jest loads the CommonJS version of some packages. See this issue here: Error TS2351 for new SchemaBuilder when testing with ts-jest

@DavidRigglemanININ
Copy link

Does anyone have a workaround for when your jest config file and global setup files are in TS? It does work if my production tsconfig file sets "noEmitOnError" to false, but I don't really want to do that for production code. But with the ts-jest code seeming to invoke ts-node (from what I read) and using my default tsconfig, some of the above workarounds don't seem to work such as the transform or a custom tsconfig file.

Also, is this project dead? There hasn't been a release for over 6 months. I'm trying to figure out if we need to start looking at other projects if this project is indeed no longer being maintained.

wolfy1339 added a commit to octokit/webhooks.js that referenced this issue Feb 11, 2024
There is currently a bug in ts-node where it completely ignores the `module` and `moduleResolution` options
kulshekhar/ts-jest#4198
wolfy1339 added a commit to octokit/webhooks.js that referenced this issue Feb 14, 2024
* feat: migrate to ESM

* build: fixup `generate-types` script

* build: update `ts-node` config to use ESM

* build: disable `verbatimModuleSyntax` for `ts-node`

There is currently a bug in ts-node where it completely ignores the `module` and `moduleResolution` options
kulshekhar/ts-jest#4198

* test: use ESM export for jest
@tobice
Copy link

tobice commented Feb 24, 2024

I came here because I wanted to speed up my ts-jest tests by applying isolatedModules: true, which is when I started receiving this error.

I solved by it putting the following into my tsconfig.js:

        "module": "ESNext",
        "moduleResolution": "Node",

I don't fully understand the practical difference between NodeNext and ESNext but it seems to work fine for my case (I just had to change how I import certain npm packages).

Running a trivial test went from 5 seconds to 1 ms.

@erunion
Copy link

erunion commented Jul 10, 2024

Confirmed that the work in v29 resolves this for us on a module and moduleResolution of node16. Thanks @ahnpnl!

@drweizak
Copy link

This fix i breaking our packages.
We have some packages in our monorepo that fail with the following setup:

package.json:

"type": "module",

tsconfig.json:

  "compilerOptions": {
    "outDir": "./dist",
    "lib": ["ES2023"],
    "module": "NodeNext",
    "target": "ESNext",
    "skipLibCheck": true,
    "moduleResolution": "NodeNext",
    "incremental": true,
    "declaration": true,
}

tsconfig.test.json:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "types": ["node", "jest"],
    "typeRoots": ["../../node_modules/@types"],
    "moduleResolution": "Node",
    "resolveJsonModule": true
  },
  "include": ["./src/index.spec.ts"],
  "exclude": []
}

jest.config.cjs:

const config = {
  preset: 'ts-jest',
  testEnvironment: 'node',

  extensionsToTreatAsEsm: ['.ts'],

  transform: {
    '^.+\\.(ts)$': [
      'ts-jest',
      {
        useESM: true,
        tsconfig: 'tsconfig.test.json',
        diagnostics: {
          ignoreCodes: ['TS151001'],
        },
      },
    ],
  },

  moduleNameMapper: {
    '^(\\.{1,2}/.*)\\.js$': '$1',
  },

  testMatch: ['**/?(*.)+(spec).[tj]s?(x)'],

  testPathIgnorePatterns: ['/node_modules/', '/dist/'],

  verbose: true,

  reporters: ['<rootDir>/minimalReporter.cjs'],
}

module.exports = config

Can anyone please help me understand what i am doing wrong?

I am having issues importing .json files with "import * as xxx from 'x/x/x.json'"
They are convertes into objects, while they are defined as arrays.

@ahnpnl
Copy link
Collaborator

ahnpnl commented Jul 17, 2024

@drweizak would you please create a reproduce problem with example apps https://github.com/kulshekhar/ts-jest/tree/main/examples It would be easier to investigate. Thank you.

@drweizak
Copy link

@drweizak would you please create a reproduce problem with example apps https://github.com/kulshekhar/ts-jest/tree/main/examples It would be easier to investigate. Thank you.

Thank you for your time! i found out the problem was related how i was importing my files. All is good now :)

before:
import * as x from 'file.json'

now:
import x from 'file.json'

@ahnpnl
Copy link
Collaborator

ahnpnl commented Jul 18, 2024

@drweizak is it related to https://www.typescriptlang.org/tsconfig/#allowSyntheticDefaultImports? We did change a bit the behavior there in ff4b302

@ahnpnl ahnpnl reopened this Aug 19, 2024
@ahnpnl ahnpnl pinned this issue Sep 13, 2024
@ahnpnl ahnpnl changed the title [Bug]: TS 5.2 error TS5110: Option 'module' must be set to 'Node16' when option 'moduleResolution' is set to 'Node16' Support Node16/NodeNext value for moduleResolution Sep 13, 2024
Clashsoft added a commit to Morphclue/apollusia that referenced this issue Oct 8, 2024
Clashsoft added a commit to Morphclue/apollusia that referenced this issue Oct 8, 2024
* feat: nx migrate and angular update

* feat: turn off no-unused-expressions

* fix: imports formatting in app.module.ts

* feat: update mongodb-memory-server, ical-generator and reflect-metadata

* fix: use NodeNext moduleResolution

* fix(ci): Node version 22

* revert: upgrade mean-stream/nestx

* feat: upgrade @mean-stream/nestx

* fix: module NodeNext in tsconfig

* feat: pnpm 9.12.0

* feat: NodeNext for tsconfig.spec.json

* test: Revert ts-jest to 29.2.3

See: kulshekhar/ts-jest#4198
See:  kulshekhar/ts-jest#4552

---------

Co-authored-by: Adrian Kunz <a.kunz@uni-kassel.de>
@kirkwaiblinger
Copy link

kirkwaiblinger commented Nov 22, 2024

The issue that I'm encountering is that JSON modules, especially when imported dynamically, do not seem to be resolved the same way as tsc/node when using ts-jest. See https://github.com/kirkwaiblinger/typescript-default-json/ for some examples.

It's been hard to figure out what behavior is even correct here, since it touches on

  • moduleResolution
  • node runtime semantics
  • TS's compatibility mechanisms (synthetic default imports and esmodule interop)
  • resolveJsonModule (and import attributes?)

But the ts-jest and tsc/node behavior definitely do not match.

Note that the behavior when using swc does more or less seem to match node's runtime behavior: https://github.com/kirkwaiblinger/typescript-default-json/tree/swc-variant

@amitbeck
Copy link

amitbeck commented Dec 1, 2024

It's been hard to figure out what behavior is even correct here, since it touches on

  • moduleResolution
  • node runtime semantics
  • TS's compatibility mechanisms (synthetic default imports and esmodule interop)
  • resolveJsonModule (and import attributes?)

But the ts-jest and tsc/node behavior definitely do not match.

I've encountered an issue similar to the one @kirkwaiblinger is describing, but not with importing a JSON module. The issue I'm having is actually related to importing the type Delta which is declared as the default export of the quill-delta package.

tsc passes, but jest with ts-jest fails with 'Delta' only refers to a type, but is being used as a namespace here. This alleged TypeScript error is for using Delta.default because Delta's type definition uses declare class, and setting the module TSConfig option to 'NodeNext' causes the imported Delta type to be interpreted as a namespace.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 Bug Confirmed Bug is confirmed
Projects
None yet
Development

Successfully merging a pull request may close this issue.