How to Fix TypeError [ERR_UNKNOWN_FILE_EXTENSION] for .ts Files in Node.js

intermediate💚 Node.js2026-06-26| Node.js (v16.x, v18.x, v20.x+), TypeScript, macOS/Linux/Windows, package.json with "type": "module"

Error Message

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /path/to/file.ts
#nodejs#esm#typescript#tsx#ts-node

The ErrorYou’ve likely just added "type": "module" to your package.json to enjoy modern ES Modules. However, the moment you try to run a TypeScript file, Node.js crashes. Instead of executing your code, the runtime throws a frustrating extension error:

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /path/to/file.ts
    at new NodeError (node:internal/errors:399:5)
    at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:79:11)

Why This HappensNode.js does not support TypeScript natively. When you enable ES Modules (ESM), Node.js uses a strict loader that only recognizes .js, .mjs, and .json files. Unlike the older CommonJS system, the ESM loader won't let ts-node easily hook into the runtime without specific flags.

If you run node script.ts, Node looks at the extension and immediately stops. It simply doesn't know what to do with a .ts file in an ESM context.

Solution 1: Use 'tsx' (The Modern Standard)For development, tsx is currently the most reliable tool. It is a drop-in replacement for Node.js built on esbuild, making it up to 10x faster than traditional ts-node. It handles ESM and TypeScript with zero extra configuration.

1. Install tsx```

npm install --save-dev tsx


### 2. Run your fileSimply swap `node` or `ts-node` for `tsx`:

npx tsx ./src/index.ts


This works because `tsx` automatically registers the necessary loaders in the background. You won't have to manage complex flags or experimental warnings.
## Solution 2: Using 'ts-node' with ESM LoaderIf your workflow depends on `ts-node`, you must explicitly tell Node.js how to handle the ESM loader. The command you use depends on your specific Node.js version.
### For Node.js v20.6.0+ or v18.19.0+Recent updates introduced the `--import` flag. This is the stable, modern way to register TypeScript support:

node --import ts-node/register ./src/index.ts


### For Older Node.js Versions (v16.x or early v18)You must use the experimental loader flag. Note that Node.js will display a warning about this being an experimental feature:

node --loader ts-node/esm ./src/index.ts


### Update your tsconfig.jsonTo make `ts-node` work with ESM, your `tsconfig.json` needs a specific `ts-node` configuration block:

{ "compilerOptions": { "module": "NodeNext", "moduleResolution": "NodeNext" }, "ts-node": { "esm": true } }


## Solution 3: The Production Fix (Transpilation)Running `.ts` files directly is great for coding, but it's risky for production. The most robust approach is to compile your code to standard JavaScript before deploying.
### 1. Build the project```
npx tsc

2. Run the outputOnce compiled, run the resulting JavaScript from your build folder (usually dist or out):

node dist/index.js

Because the output is standard .js, Node's ESM loader handles it without any complaints. Note: In ESM mode, your TypeScript import statements must include the .js extension, even if the source file is .ts.

Quick VerificationNot sure if it's fixed? Create a file named check.ts and add this code:

const message: string = "Loader is working!";
console.log(message);

Run npx tsx check.ts. If you see the message without a stack trace, your environment is ready.

Key Takeaways

  • Use .js in imports: ESM requires full file extensions. Always write import { tool } from './tool.js';.
  • Try .mts: Using the .mts extension forces Node to treat a file as an ES Module regardless of your package.json settings.
  • Stay Updated: If you are on a version older than Node 18, consider upgrading to v20+ to access the more stable --import flag.

Related Error Notes