You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在使用TypeScript编写的ESM模块中处理Jest的相对导入问题?

Fix "Cannot find module './catalog.js' from 'src/index.ts'" in Jest + ts-jest + ESM Setup

I’ve run into this exact conflict before—your setup makes total sense for ESM output, but ts-jest’s real-time transpilation doesn’t natively map those .js extensions in your TS imports back to the actual .ts files. Here’s how to fix it step by step:

Solution Steps

1. Add Module Path Mapping (Critical Fix)

Add a moduleNameMapper to your jest.config.js to redirect requests for .js files to their corresponding .ts sources. This tells Jest to look for the original TypeScript files instead of the non-existent compiled JS files during testing:

moduleNameMapper: {
  // Match relative paths ending with .js, and map them to .ts files
  '^(\\.{1,2}/.*)\\.js$': '$1.ts',
}

If you work with .tsx files too, adjust the regex to match both:

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

2. Configure Jest to Recognize ESM Extensions

Add extensionsToTreatAsEsm to ensure Jest treats your TypeScript files as ESM modules, aligning with your compile target and avoiding parsing errors:

extensionsToTreatAsEsm: ['.ts', '.tsx'],

3. Align tsconfig.json with Node.js ESM Rules

Update your tsconfig.json to use a module resolution strategy that matches Node.js ESM behavior, so TypeScript’s compilation and Jest’s transpilation stay consistent:

{
  "compilerOptions": {
    "module": "ES2020",
    "moduleResolution": "NodeNext", // Or Node16, matches your ES module setup
    "target": "ES2020",
    "esModuleInterop": true,
    "skipLibCheck": true,
    "strict": true
  }
}

Full Updated jest.config.js

Putting it all together, your config should look like this:

/** @type {import('jest').Config} */
const config = {
  collectCoverage: true,
  preset: 'ts-jest/presets/default-esm-legacy',
  setupFiles: ['./src/jest-setup.ts'],
  testEnvironment: 'node',
  testMatch: ['**/__tests__/**/*.[t]s?(x)', '**/?(*.)+(spec|test).[t]s?(x)'],
  extensionsToTreatAsEsm: ['.ts', '.tsx'],
  moduleNameMapper: {
    '^(\\.{1,2}/.*)\\.js$': '$1.ts',
  },
  transform: {
    '^.+\\.tsx?$': [
      'ts-jest',
      { useESM: true },
    ],
  }
};
export default config;

Why This Works

Your choice to add .js extensions in TS imports is correct for Node.js ESM compliance—TypeScript won’t auto-add these extensions during compilation, so manual inclusion is necessary. The problem is that ts-jest tries to resolve the exact path you wrote, but the .js files don’t exist in your src directory yet.

The moduleNameMapper redirects those .js path requests to the actual .ts files, while extensionsToTreatAsEsm ensures Jest handles those files as ESM modules, matching your production build setup.

内容的提问来源于stack exchange,提问作者Harshal Patil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 16:29:07