jest icon indicating copy to clipboard operation
jest copied to clipboard

[Feature]: Allow usage of tsm instead of ts-node?

Open karlhorky opened this issue 4 years ago β€’ 20 comments

πŸš€ 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

  • tsm is lighter weight and faster than ts-node
  • if projects are already using tsm for other tasks, it would be nice to not have to also install ts-node only 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

karlhorky avatar Oct 22 '21 19:10 karlhorky

PR very much welcome!

SimenB avatar Oct 22 '21 22:10 SimenB

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:

  1. Use @swc/cli in a child process like this: npx swc jest.config.,ts -o /node_modules/jest-config/_jest.config.js where /node_modules/jest-config/_jest.config.js is a temporary file.
  2. require("/node_modules/jest-config/_jest.config.js") which gives us the config object.
  3. 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?

jensmeindertsma avatar Nov 02 '21 17:11 jensmeindertsma

would that work if said file imported another ts file? or will swc bundle?

SimenB avatar Nov 02 '21 17:11 SimenB

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 ☺️

jensmeindertsma avatar Nov 02 '21 17:11 jensmeindertsma

@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)

SimenB avatar Nov 02 '21 17:11 SimenB

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?

jensmeindertsma avatar Nov 02 '21 18:11 jensmeindertsma

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

SimenB avatar Nov 02 '21 18:11 SimenB

What would be breaking about removing ts-node? Depending on it's type-checking features would be one? I can do a CLI option

jensmeindertsma avatar Nov 02 '21 18:11 jensmeindertsma

For people currently using ts-node it would stop working - it's a peer dependency, not a dependency

SimenB avatar Nov 02 '21 18:11 SimenB

Ah okay. I will implement esbuild under a flag

jensmeindertsma avatar Nov 02 '21 18:11 jensmeindertsma

What about a fallback mechanism where Jest will try to parse the config file with esbuild if ts-node is not installed?

jensmeindertsma avatar Nov 04 '21 18:11 jensmeindertsma

If config loading happens within a CJS context, something like this would work just fine: https://boostlib.dev/docs/module#commonjs-requires

milesj avatar Nov 04 '21 18:11 milesj

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.

github-actions[bot] avatar Nov 04 '22 18:11 github-actions[bot]

Not stale? There is also now another alternative called tsx

karlhorky avatar Nov 05 '22 13:11 karlhorky

Current thinking: https://github.com/facebook/jest/issues/13143#issuecomment-1249081951

I.e. allowing a user to specify which loader to use.

SimenB avatar Nov 07 '22 17:11 SimenB

Both tsm and tsx support would be provided by https://github.com/facebook/jest/pull/13521 πŸŽ‰

LinusU avatar Feb 01 '23 03:02 LinusU

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.

github-actions[bot] avatar Feb 01 '24 04:02 github-actions[bot]

Not stale

karlhorky avatar Feb 01 '24 06:02 karlhorky

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

karlhorky avatar Aug 08 '25 10:08 karlhorky

Now that node can run TS natively, Jest should use that instead of needing 3rd party libraries

Stanzilla avatar Oct 06 '25 10:10 Stanzilla