|
| 1 | +--- |
| 2 | +layout: post |
| 3 | +title: Jest TypeScript ESM support |
| 4 | +date: 2026-02-02 19:36:15 |
| 5 | +excerpt: How to enable ECMAScript Modules (ESM) support for Jest tests written in TypeScript. |
| 6 | +categories: jest test esm typescript |
| 7 | +--- |
| 8 | + |
| 9 | +This post goes over how to enable [ECMAScript Modules (ESM) support](https://jestjs.io/docs/ecmascript-modules) for [Jest](https://jestjs.io/) tests written in TypeScript. |
| 10 | + |
| 11 | +## Prerequisites |
| 12 | + |
| 13 | +Your Jest is configured with [ts-jest](https://kulshekhar.github.io/ts-jest/): |
| 14 | + |
| 15 | +```ts |
| 16 | +// jest.config.ts |
| 17 | +import type { Config } from 'jest'; |
| 18 | + |
| 19 | +const config: Config = { |
| 20 | + preset: 'ts-jest', |
| 21 | +}; |
| 22 | + |
| 23 | +export default config; |
| 24 | +``` |
| 25 | + |
| 26 | +## Scripts |
| 27 | + |
| 28 | +Update your `package.json` script "test": |
| 29 | + |
| 30 | +```diff |
| 31 | + { |
| 32 | + "scripts": { |
| 33 | +- "test": "jest" |
| 34 | ++ "test": "node --experimental-vm-modules $(npx which jest)" |
| 35 | + } |
| 36 | + } |
| 37 | +``` |
| 38 | + |
| 39 | +> `npx which jest` evaluates to `node_modules/.bin/jest`. |
| 40 | +
|
| 41 | +Or alternatively: |
| 42 | + |
| 43 | +```diff |
| 44 | + { |
| 45 | + "scripts": { |
| 46 | +- "test": "jest" |
| 47 | ++ "test": "NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest |
| 48 | + } |
| 49 | + } |
| 50 | +``` |
| 51 | + |
| 52 | +## Configs |
| 53 | + |
| 54 | +Update your Jest config to [transform using ESM](https://kulshekhar.github.io/ts-jest/docs/getting-started/options/useESM): |
| 55 | + |
| 56 | +```diff |
| 57 | + // jest.config.ts |
| 58 | + import type { Config } from 'jest'; |
| 59 | + |
| 60 | + const config: Config = { |
| 61 | +- preset: 'ts-jest', |
| 62 | ++ extensionsToTreatAsEsm: ['.mts', '.ts'], |
| 63 | ++ moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1' }, |
| 64 | ++ transform: { '^.+\\.m?[tj]sx?$': ['ts-jest', { useESM: true }] }, |
| 65 | + }; |
| 66 | + |
| 67 | + export default config; |
| 68 | +``` |
| 69 | + |
| 70 | +Set `module` to `esnext` (or `es2022`) in your `tsconfig.json`: |
| 71 | + |
| 72 | +```diff |
| 73 | + { |
| 74 | + "compilerOptions": { |
| 75 | + "target": "es2022", |
| 76 | ++ "module": "esnext", |
| 77 | + "moduleResolution": "node" |
| 78 | + } |
| 79 | + } |
| 80 | +``` |
| 81 | + |
| 82 | +## Tests |
| 83 | + |
| 84 | +Import [`jest`](https://jestjs.io/docs/ecmascript-modules#differences-between-esm-and-commonjs) to access the object: |
| 85 | + |
| 86 | +```ts |
| 87 | +import { jest } from '@jest/globals'; |
| 88 | +``` |
| 89 | + |
| 90 | +```ts |
| 91 | +jest.fn(); |
| 92 | +``` |
| 93 | + |
| 94 | +Use `await import` to import relative files: |
| 95 | + |
| 96 | +```ts |
| 97 | +const { myUtil } = await import('./my-util.js'); |
| 98 | +``` |
| 99 | + |
| 100 | +> ESM relative import must include the file extension. |
| 101 | +
|
| 102 | +[Mock](https://jestjs.io/docs/ecmascript-modules#module-mocking-in-esm) a module with `jest.unstable_mockModule`: |
| 103 | + |
| 104 | +```ts |
| 105 | +jest.unstable_mockModule('node:os', () => ({ |
| 106 | + platform: jest.fn(), |
| 107 | +})); |
| 108 | +``` |
| 109 | + |
| 110 | +> Both the 1st and 2nd arguments are required. |
| 111 | +
|
| 112 | +[Unmock](https://jestjs.io/docs/ecmascript-modules#module-unmocking-in-esm) with `jest.unstable_unmockModule`: |
| 113 | + |
| 114 | +```ts |
| 115 | +jest.unstable_unmockModule('node:os'); |
| 116 | +``` |
0 commit comments