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.

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.tsOK, 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.tsOK, 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.
| Concern | tsx | ts-node |
|---|---|---|
| Startup time | Instant (esbuild) | 2-5 seconds |
| ESM support | Native | Requires --esm and often still fails |
emitDecoratorMetadata | Not supported | Supported |
Full tsconfig.json respect | Partial | Full |
| Type-checking at run time | No | Optional |
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.
tsccompiles 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-nodecompiles 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. ๐
Related Posts to tsx vs ts-node: Time to Drop ts-node for tsx

TypeScript: Mapped Type Magic ๐ช
Wed, 13 Mar 2024

Vite: How to handle `.node` files
Mon, 08 Apr 2024

Using Vite To Rebuild Local Dependencies in an NPM Workspace
Thu, 18 Apr 2024

TypeScript: Branded Types ๐ง
Mon, 22 Apr 2024

How to deploy Procaptcha on your website or app
Wed, 20 Sept 2023

actions/cache@v3 restore: GitHub Actions Cache Fix
Tue, 18 Jun 2024

How to Test Your Ansible Playbooks Locally
Tue, 30 Jul 2024

How Does CAPTCHA Collect User Data? The Reality
Fri, 25 Apr 2025

Monorepo vs Multirepo Architecture: How to Decide?
Thu, 01 May 2025

Mastering Versioning: A Guide to Software Stability
Fri, 02 May 2025

Independent vs Locked Versioning in a Workspace
Sat, 03 May 2025

Streamlining Releases: Building Scalable CICD Pipelines with Changesets
Tue, 06 May 2025

PHP Views Package - Templating Made Easy with Blade and Model-Driven Approach
Mon, 19 May 2025

Reactive Frameworks Cheatsheet - React, Vue, Svelte and Angular
Mon, 19 May 2025

We cut our Mongo DB costs by 90% by moving to Hetzner
Wed, 12 Nov 2025

We suffered MongooseJS so you don't have to
Tue, 02 Dec 2025

How to Add CAPTCHA to Fastly CDN
Tue, 20 Jan 2026
Faking browsers is easy โ but not at scale
Thu, 21 May 2026

How to Stop PHP Form Spam (Without a Plugin)
Wed, 24 Jun 2026
