Alright, let’s get one thing straight: compiling your TypeScript with tsc every single time you want to run a tiny script is a fantastic way to lose your will to live. It’s the programming equivalent of having to assemble a car engine just to drive to the mailbox. You’re a developer, not a build-system masochist. This is where ts-node and tsx come in—they’re your power tools for skipping the “generate a .js file” middleman and running your beautiful TypeScript code directly.

Think of them as supremely clever interpreters. They perform all the necessary steps—transpilation, type checking (sometimes), and execution—in one seamless, behind-the-scenes motion. It’s pure magic, and like all good magic, it’s just applied computer science.

The Old Guard: ts-node

ts-node is the veteran. It’s been around the block, it’s reliable, and it has a few quirks you need to know about. You install it as a development dependency:

npm install -D ts-node

Now, instead of node script.js, you run:

npx ts-node script.ts

And boom. It just works. It reads your tsconfig.json, compiles the script.ts in memory, and feeds the resulting JavaScript to Node.js. No littering your directory with .js files. Beautiful.

But here’s its first, and most important, quirk: by default, ts-node does type checking. This is a good thing! It means if you have a type error, it will refuse to run your code, saving you from runtime surprises. However, this compilation step can be slow for large codebases. If you just want to run the code and skip the type checking (maybe you’re iterating quickly and using ts-node alongside your editor’s type checking), use the --transpile-only flag. It’s dramatically faster.

npx ts-node --transpile-only script.ts

The New Hotness: tsx

Now, meet tsx. It’s the new kid on the block, and it’s blisteringly fast. How? It’s not a TypeScript compiler itself. Instead, it’s a clever wrapper around Node.js’s built-in ES module loader. It uses the incredibly speedy esbuild under the hood to transpile your TypeScript on the fly.

Install it:

npm install -D tsx

Run your script:

npx tsx script.ts

The speed difference is often noticeable. tsx is designed for a world of ES modules (import/export) and, in my experience, is less fussy about configuration. However, and this is a big however: tsx does not do type checking. It only transpiles. It will happily run code with type errors. This makes it fast, but it means you must rely on your IDE or a separate tsc --noEmit command to catch type issues. It’s a trade-off: raw speed for safety.

Choosing Your Weapon: ts-node vs. tsx

So, which one should you use? Here’s my trench advice:

  • Use tsx by default. Its speed is a genuine quality-of-life improvement, especially in development. Just make sure you have a process (like your editor’s built-in type checking or a pre-commit hook) to catch type errors. You’re living dangerously, but you’re living fast.
  • Use ts-node when you need a safety net. If you’re running a script in production (though be careful with that!) or a one-off where correctness is paramount, ts-node’s built-in type checking is a valuable feature. The --transpile-only flag also makes it a viable, fast competitor to tsx.

The “Shebang” Trick for Executables

This is a pro move. You can make a .ts file directly executable on Unix-based systems (Linux, macOS) by using a shebang. This is fantastic for writing CLI tools in TypeScript.

For ts-node:

#!/usr/bin/env -S npx ts-node --transpile-only

console.log("I'm a real boy! A real executable script!");

For tsx:

#!/usr/bin/env -S npx tsx

console.log("I'm an even faster real boy!");

Make the file executable with chmod +x your-script.ts and then you can run it directly: ./your-script.ts. The -S flag for env is crucial; it splits the following argument so npx and ts-node are treated as separate commands.

The Gotchas and Rough Edges

No tool is perfect. Here’s what will bite you:

  1. No Native ECMAScript Modules (ESM) in ts-node by default: If your package.json has "type": "module", ts-node will complain about your import statements. You need to use the --esm flag to enable ESM support. tsx, built for ESM, handles this seamlessly.
    npx ts-node --esm script.ts
    
  2. Debugging: Both tools work with debugger statements and Node.js inspectors, but sometimes the compiled source maps (which map the executed JS back to your TS) can get confused. If your breakpoint lands on the wrong line, blame the source map, not your sanity.
  3. It’s For Development: While you can use these in production, think twice. The overhead of on-the-fly compilation is usually unnecessary. For production, you should pre-compile your code with tsc to get optimized, static JavaScript files. Use ts-node or tsx for development, scripts, and prototyping.

There you have it. Stop compiling and start running. Your sanity will thank you.