ts-node and mocha 'TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"' error even with "ts-node/esm" loader and CommonJS modules

2 min read 05-10-2024
ts-node and mocha 'TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"' error even with "ts-node/esm" loader and CommonJS modules


Debugging "TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"" with ts-node and Mocha

The Problem:

You're using ts-node with Mocha to run your TypeScript tests, but you encounter the error "TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"". This error happens when Mocha tries to load your TypeScript files directly without proper configuration.

Simplified Explanation:

Imagine trying to play a song on a CD player without knowing the format. Mocha is the CD player, TypeScript files are the songs, and ts-node is the translator that makes the songs playable. Without the translator, Mocha can't understand your TypeScript code.

The Scenario:

Let's say you have a simple TypeScript file called myTest.ts:

// myTest.ts
import { expect } from 'chai';

describe('My Test Suite', () => {
  it('should pass', () => {
    expect(true).to.be.true;
  });
});

And your Mocha test script (test.js):

// test.js
require('ts-node/register');
const mocha = require('mocha');

mocha.run();

You've included ts-node/register to tell Mocha to use ts-node to load your TypeScript files. However, you still get the error.

The Root Cause:

The issue lies in the way ts-node handles CommonJS modules. By default, ts-node/register uses a loader that's designed for ES Modules. While this works well for ES Modules, CommonJS modules require a different approach.

The Solution:

To fix the error, you need to use the dedicated ts-node/esm loader for CommonJS modules. Replace ts-node/register with ts-node/esm in your Mocha test script:

// test.js
require('ts-node/esm');
const mocha = require('mocha');

mocha.run();

Explanation:

ts-node/esm specifically instructs ts-node to treat your TypeScript files as CommonJS modules. This allows Mocha to understand and execute your tests correctly.

Additional Insights:

  • Using require: While require is suitable for CommonJS, you can use import for ES Modules in your TypeScript files. However, ensure that your Mocha configuration correctly handles the module system.

  • tsconfig.json: Consider using a tsconfig.json file to manage TypeScript compilation options. You can configure module and moduleResolution to align with your project's needs.

Example:

Let's modify the myTest.ts file to use require:

// myTest.ts
const { expect } = require('chai');

describe('My Test Suite', () => {
  it('should pass', () => {
    expect(true).to.be.true;
  });
});

Now, running the test.js script with ts-node/esm will execute the tests successfully.

Conclusion:

The "TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"" error arises from a mismatch between Mocha's expectations and ts-node's module handling. Using ts-node/esm ensures proper loading of CommonJS modules in your TypeScript tests, allowing Mocha to run them smoothly.

References and Resources: