[Feature]: Allow usage of tsm instead of ts-node?
π Feature Proposal
Jest allows for configuration in TypeScript via ts-node:
https://github.com/facebook/jest/blob/7f39f0a589703191a0cd3c6db558920281f7195f/docs/Configuration.md?plain=1#L37
It would be great to also enable support for tsm
Motivation
tsmis lighter weight and faster thants-node- if projects are already using
tsmfor other tasks, it would be nice to not have to also installts-nodeonly for Jest
Example
No response
Pitch
Not entirely sure I understand this field, but maybe:
It fits Jest's ideology of being fast and enabling modern techniques
PR very much welcome!
The disadvantage to using tsm is that there is no programmatic way to invoke it. This is a problem because then we need to spawn a child process in which we run node --loader tsm jest.config.ts to import the config file. Then we must pass back the imported config to Jest. This can't be done across process boundaries without sacrificing support for function config files.
What I propose instead:
- Use
@swc/cliin a child process like this:npx swc jest.config.,ts -o /node_modules/jest-config/_jest.config.jswhere/node_modules/jest-config/_jest.config.jsis a temporary file. require("/node_modules/jest-config/_jest.config.js")which gives us the config object.- Delete the temporary file. -> Now we have the config object available.
I chose swc because of the stability. I know there is also esbuild which tsm uses, and they are similar in size.
@SimenB would you accept a PR implementing this approach?
would that work if said file imported another ts file? or will swc bundle?
If said file imported another TS file, it wouldn't work. I know esbuild can do bundling, that might be an option. I don't know many cases in which you might import from other files though, but yeah, I'd be happy to use esbuild instead and do bundling. Let me know what you prefer βΊοΈ
@swc/core has a bundle export: https://www.runpkg.com/?@swc/[email protected]/index.js#229
(I don't care if swc or esbuild is chosen, I've never used either and haven't cared to check any of them out)
Ah, okay. I'll look into it. Just to confirm, you are open to a PR removing ts-node and implementing support for jest.config.ts files with swc or esbuild?
I don't think we should remove ts-node (but as it would be a breaking change, but also since I don't think any of the alternatives does any type checking?), but making it configurable in some way (--config-loader=blah or some such?) sounds reasonable
What would be breaking about removing ts-node? Depending on it's type-checking features would be one? I can do a CLI option
For people currently using ts-node it would stop working - it's a peer dependency, not a dependency
Ah okay. I will implement esbuild under a flag
What about a fallback mechanism where Jest will try to parse the config file with esbuild if ts-node is not installed?
If config loading happens within a CJS context, something like this would work just fine: https://boostlib.dev/docs/module#commonjs-requires
This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 30 days.
Not stale? There is also now another alternative called tsx
Current thinking: https://github.com/facebook/jest/issues/13143#issuecomment-1249081951
I.e. allowing a user to specify which loader to use.
Both tsm and tsx support would be provided by https://github.com/facebook/jest/pull/13521 π
This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 30 days.
Not stale
Alternative: esbuild-register
Jest v30 (specifically PR https://github.com/jestjs/jest/pull/15190 by @k-rajat19 ) introduced docblock loaders, which allow esbuild-register to run on the config.
First add esbuild-register to devDependencies.
Then, add the docblock loader at the top, using esbuild-register:
jest.config.ts
/** @jest-config-loader esbuild-register */
import type { Config } from 'jest';
const config: Config = {
// ...
};
export default config;
tsm uses esbuild internally, so this is a similar approach, while removing some layers from the tsm approach.
Demo: https://github.com/upleveled/next-js-example-winter-2025-eu/blob/main/jest.config.ts#L1
Now that node can run TS natively, Jest should use that instead of needing 3rd party libraries