Overriding `tsconfig.json` for ts-node in mocha

TypeScript allows you to override a configuration file. Rather than hard-code JSON in an environment variable as mentioned in the other solutions, specify the overridden configuration path in the environment. The TS_NODE_PROJECT environment variable can be used for this.

TS_NODE_PROJECT='./tsconfig.commonjs.json'

So if your main config is:

tsconfig.json

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
   }
}

You can create another configuration that overrides the module setting.

tsconfig.commonjs.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "module": "commonjs"
  }
}

When you run mocha, specify the overridden configuration to use:

"test": "TS_NODE_PROJECT='./tsconfig.commonjs.json' mocha -r ts-node/register test/**/*.spec.ts*"

This makes it very easy to further customize your tsconfig just for mocha testing. You can even run ts-node (outside of mocha) directly specifying that path:

ts-node -P tsconfig.commonjs.json -r myFile.ts 

In package.json - scripts section:

"test": "TS_NODE_PROJECT=src mocha"

picks up my tsconfig.json in the src directory of my project, overriding the default tsconfig.json.

OP can achieve same by using test instead of src


You need to set the configuration through the TS_NODE_COMPILER_OPTIONS environment variable

Example code on an unix machine:

TS_NODE_COMPILER_OPTIONS='{"module":"commonjs"}' \
mocha --require ts-node/register 'test/**/*.spec.{ts,tsx}'

Explanation extracted from the repository documentation


CLI and Programmatic Options

Environment variable denoted in parentheses.

  • -T, --transpile-only Use TypeScript's faster transpileModule (TS_NODE_TRANSPILE_ONLY, default: false)
  • -I, --ignore [pattern] Override the path patterns to skip compilation (TS_NODE_IGNORE, default: /node_modules/)
  • -P, --project [path] Path to TypeScript JSON project file (TS_NODE_PROJECT)
  • -C, --compiler [name] Specify a custom TypeScript compiler (TS_NODE_COMPILER, default: typescript)
  • -D, --ignore-diagnostics [code] Ignore TypeScript warnings by diagnostic code (TS_NODE_IGNORE_DIAGNOSTICS)
  • -O, --compiler-options [opts] JSON object to merge with compiler options (TS_NODE_COMPILER_OPTIONS)
  • --files Load files from tsconfig.json on startup (TS_NODE_FILES, default: false)
  • --pretty Use pretty diagnostic formatter (TS_NODE_PRETTY, default: false)
  • --skip-project Skip project config resolution and loading (TS_NODE_SKIP_PROJECT, default: false)
  • --skip-ignore Skip ignore checks (TS_NODE_SKIP_IGNORE, default: false)
  • --log-error Logs errors of types instead of exit the process (TS_NODE_LOG_ERROR, default: false)
  • --prefer-ts-exts Re-order file extensions so that TypeScript imports are preferred (TS_NODE_PREFER_TS_EXTS, default: false)

--compilerOptions wont' work.

What you need to do is customize how you register ts-node. My case was a little bit different from yours, I wanted it to use test/tsconfig.json, which contained settings needed by my test code. If I just used --require ts-node/register, it was using a default configuration that did not contain the settings needed to run my tests.

What I did was:

  1. Create a file test/tshook.js. It contains:

    require("ts-node").register({
      project: "test/tsconfig.json",
    });
    
  2. I edited my test/mocha.opts to have:

    --require test/tshook.js
    test/**/*.ts
    

This should will pass the desired setting to ts-node:

require("ts-node").register({
  compilerOptions: {
    module: "commonjs",
  },
});