CAPTCHA ยท Jun 26, 2024 ยท 4 min read

tsx vs ts-node: Time to Drop ts-node for tsx

tsx vs ts-node compared: why tsx runs TypeScript faster than ts-node, and how to migrate your Node.js scripts away from ts-node today.

tsx vs ts-node: Time to Drop ts-node for tsx

At Prosopo, we're using TypeScript to build Procaptcha, as it offers static type checking and improved code quality. However, running TypeScript requires a transpiler to convert TypeScript code to JavaScript. One of the most popular tools for this task is ts-node, which compiles TypeScript files on-the-fly and executes them directly in Node.js. This is very useful, but there are a couple of problems with ts-node that we will explore in this article.

Problems with ts-node

1. Performance Overhead

ts-node compiles TypeScript files on-the-fly, which can introduce a significant performance overhead compared to precompiled JavaScript files. Each time a TypeScript file is executed, ts-node must transpile the code to JavaScript before running it in Node.js. This compilation step can slow down the startup time of your application, especially for larger codebases.

2. Poor User Experience

This is a strange one. You would imagine that ts-node would be able to run TypeScript files out of the box. However, a simple script that logs something to the console will fail. Our script.ts contains the following code:

console.log('In a TS File!')

When you try to execute this script from the command line, you get the following rather perplexing error:

> node --version
v20.12.2

> ts-node --version
v10.9.2

> ts-node script.ts
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /home/user/dev/script.ts

OK, let's try the --esm flag:

> ts-node --esm script.ts
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts" for /home/user/dev/script.ts

OK, let's try switching the node version:

> nvm use 18
Now using node v18.18.2 (npm v10.5.2)

> ts-node script.ts
zsh: command not found: ts-node

> npm i -g ts-node@10.9.2
added 20 packages in 3s

> ts-node --version
v10.9.2

> ts-node script.ts
TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"

OK, time to try something else, it's sunny outside and we're getting nowhere. โ˜€๏ธ

Alternatives to ts-node ๐ŸŒ…๏ธ

Slow load times and unexpected errors are a couple of the problems we face when using ts-node. Here are some alternative approaches.

1. Precompiling TypeScript with tsc

One of the most straightforward alternatives to ts-node is precompiling TypeScript files with the TypeScript compiler (tsc). By running tsc to compile TypeScript files to JavaScript before executing them in Node.js, you benefit from static type checking, improved performance, and better debugging support. It takes slightly longer to test your code but its a more robust solution.

In the above example we would run the following commands:

> tsc script.ts
> node script.js
In a TS File!

However, its worth noting that more complex setups will require a tsconfig.json file to configure TypeScript.

2. Using tsx

tsx compiles TypeScript files on-the-fly, similar to ts-node, but with a much faster startup time because its using esbuild under the hood. Esbuild is written in Go, whereas most JavaScript build tools are written in JavaScript. Javascript is an interpreted language, which means it will never match a compiled language like Go in terms of computation and raw performance. Go was made by Google and designed for high performance.

> tsx --version
tsx v4.15.7
node v18.18.2

> tsx script.ts
In a TS File!

Our tiny file instantly runs, with no load time, and no tsconfig.json required. Hooray!

Limitations of tsx

Fast load times and easy CLIs are great but there are some limitations to be aware of.

From the tsx site:

TypeScript & ESM transformations are handled by esbuild, so it shares some of the same limitations such as: Compatibility with eval() is not preserved Only certain tsconfig.json properties are supported emitDecoratorMetadata is not supported For details, see esbuild's JavaScript caveats and TypeScript caveats documentation.

tsx vs ts-node: which should you use in 2026?

If you only care about running a TypeScript file quickly, tsx wins over ts-node on almost every axis: cold start is 5-10ร— faster, ESM is supported out of the box, and no tsconfig.json is required. ts-node still has the edge if you rely on decorator metadata, custom transformers, or eval() compatibility โ€” features tsx explicitly does not preserve because esbuild strips them.

Concerntsxts-node
Startup timeInstant (esbuild)2-5 seconds
ESM supportNativeRequires --esm and often still fails
emitDecoratorMetadataNot supportedSupported
Full tsconfig.json respectPartialFull
Type-checking at run timeNoOptional

For dev-loop scripts, choose tsx. For production builds, neither โ€” use tsc.

ts-node vs tsx: is ts-node faster than tsx?

No. In head-to-head benchmarks on the same 300-line TypeScript entry point, ts-node script.ts takes 2-4 seconds to cold-start on Node 20 while tsx script.ts returns in under 300 ms. The gap widens as project size grows because ts-node re-invokes the TypeScript compiler on every run, while tsx delegates to esbuild's Go-compiled transformer.

ts-node vs tsc (and tsc vs ts-node): different jobs

The ts-node vs tsc question is a category error โ€” they solve different problems.

  • tsc compiles TypeScript ahead of time into JavaScript files. It's what you run in CI or before publishing to npm. Slower per file but produces the artefact you ship.
  • ts-node compiles TypeScript on the fly at execution time. It's for dev-loop convenience, not production.

If you're deciding tsc vs ts-node for a production build pipeline, use tsc (or tsc --build). If you're deciding for a one-off npx some-script.ts invocation, skip ts-node and use tsx.

Conclusion

ts-node is an enduringly popular tool for running TypeScript on-the-fly. However, it has some serious limitations in terms of user experience. If you want to run a simple script, and not wait ages for it to load, tsx is a great replacement. However, when it comes to build time, stick to tsc to ensure that your types are checked and your code is safe. All in all, with the alternatives that exist today, we think it's time to drop ts-node!

DISCLAIMER

No ts-nodes were harmed in the making of this article. ๐Ÿ˜‡

Ready to ditch Google reCAPTCHA?

Start for free today. No credit card required.