TypeScript Jest imports with .js extension cause error: Cannot find module
Asked Answered
M

6

8

I've reached a dead end trying to fix this issue. I am using the following TypeScript configuration:

{
    "compilerOptions": {
        "module": "es2022",
        "moduleResolution": "nodenext",
        "target": "es2017",
        "esModuleInterop": true,
        "forceConsistentCasingInFileNames": true,
        "strict": true,
        "skipLibCheck": true,
        "noImplicitAny": true,
        "outDir": "./dist",
        "rootDir": "./src",
        "typeRoots": [
            "./src/types", "./node_modules/@types"],
        "allowJs": true,
        "strictFunctionTypes": true,
        "noImplicitReturns": true
    },
    "include": ["./src/**/*"],
    "exclude": ["node_modules"],
    "ts-node": {
        "esm": true,
        "experimentalSpecifierResolution": true
    }
}

As you see the moduleResolution is set to nodenext, and because of that I have to explicitly add a file extension when importing, like this: import ServerError from '../models/Errors/ServerError.js';. Otherwise, I get an error that the module was not found.

Everything is working fine, but when I launch my tests I get an error: Cannot find module '../models/Errors/ServerError.js' from '../src/services/usersService.ts'. So basically jest is trying to find the file ServerError.js, but it does not exist, because all files have a .ts extension, so it should be ServerError.ts. If I try to change .js to .ts in my files I also will get an error.

I can't finish my task because of this problem, so I would appreciate any help.

Monition answered 15/9, 2022 at 17:24 Comment(0)
M
22

Finally, I've managed to solve this problem after doing some research and updating my jest config file.

/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
import type { Config } from 'jest';

const config: Config = {
    transform: {
        '\\.[jt]sx?$': 'ts-jest'
    },
    globals: {
        'ts-jest': {
            useESM: true
        }
    },
    moduleNameMapper: {
        '(.+)\\.js': '$1'
    },
    extensionsToTreatAsEsm: ['.ts']
};

With this configuration, everything is working fine. I hope that it will help somebody.

Monition answered 22/9, 2022 at 14:21 Comment(3)
I find out that configuring ts-jest through globals property is outdated. Instead, you should remove 'ts-jest' from globals and write the following to the transform property: transform: {'\\.[jt]sx?$': ['ts-jest', { useESM: true }] }. Everything else is the same.Monition
Related issue: github.com/kulshekhar/ts-jest/issues/1057 I couldn't solve this when not using "ts-jest" thoughParthenope
I guess as of now, the only essential things from the config above are transform and moduleNameMapper. At least that is what enough for my caseTumid
W
16

For me this did the trick:

  "moduleNameMapper": {
    "^(\\.\\.?\\/.+)\\.js$": "$1",
  },

(Adapted from https://github.com/kulshekhar/ts-jest/issues/1057#issuecomment-1441733977)

Wager answered 24/3, 2023 at 11:21 Comment(2)
This is enough with the recommended transform from the ts-jest docs: "^.+\\.tsx?$": ["ts-jest", ....] . It isn't needed to set moduleFileExtensions or extensionsToTreatAsEsm.Breastpin
very similar, for me it was : moduleNameMapper: { '(.+)\\.js': '$1' }Brandon
W
3

I added only moduleNameMapper key in my case, this solved the issue for me. I've been using ts-jest/presets/default-esm preset.

/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
  preset: "ts-jest/presets/default-esm",
  moduleNameMapper: {
    "(.+)\\.js": "$1",
  },
};
Willy answered 20/1 at 22:13 Comment(1)
Perfect, thank you! Additionally, in my jest test files themselves I needed to add a new import import { jest } from '@jest/globals' per https://mcmap.net/q/292831/-39-referenceerror-jest-is-not-defined-39-when-running-unit-test . Though https://mcmap.net/q/292831/-39-referenceerror-jest-is-not-defined-39-when-running-unit-test says there may be a way to do it without importing jest globally.Fascination
T
1

I solve the problem with add a config moduleFileExtensions setting in jest.config.json;

{
    ....
    "moduleFileExtensions": ["ts", "js"],
    ....
}

Tisman answered 9/2, 2023 at 3:46 Comment(0)
E
1

This can be fixed by using jest-ts-webcompat-resolver npm package.

npm i jest-ts-webcompat-resolver -D

In your jest.config.ts add:

"resolver": "jest-ts-webcompat-resolver"
Embryogeny answered 3/3, 2023 at 17:26 Comment(0)
B
1

What worked for me was a mix of the accepted answer and the settings from TS-Jest documentation.

const { defaultsESM: tsjPreset } = require('ts-jest/presets');

/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  ...tsjPreset,
moduleNameMapper: { '^(\\.|\\.\\.)\\/(.+)\\.js': '$1/$2' },

  // ....

Blackshear answered 18/12, 2023 at 6:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.