tsx vs ts-node for Running TypeScript
Compare tsx and ts-node for running TypeScript directly in Node.js. Understand speed, ESM support, watch mode, and which tool fits your workflow.
TypeScript cannot run directly in Node.js. You need a tool that strips the type annotations and feeds plain JavaScript to the runtime. The two most popular tools are ts-node and tsx. They solve the same problem, but they take very different approaches.
The main difference: ts-node uses the TypeScript compiler to process files, which is slow but gives you full type checking. tsx uses esbuild under the hood, which is dramatically faster but does no type checking. For most development workflows, faster wins.
| ts-node | tsx | |
|---|---|---|
| Engine | TypeScript compiler (tsc) | esbuild |
| Startup speed | Slower | Much faster |
| Type checking during run | Yes | No |
| ESM support | Requires configuration | Automatic |
| CJS support | Native | Native |
| Watch mode | Built-in | Built-in (Node.js watcher) |
| REPL | Yes | Yes |
| Custom transformers | Yes | No |
How tsx Works
tsx strips types from your source files using esbuild and hands the resulting JavaScript to Node.js. It never runs a full type check. This makes startup nearly instant, even for large projects.
Install it as a dev dependency and run a TypeScript file:
npm install --save-dev tsx
npx tsx src/server.tstsx automatically detects whether the file uses ESM (import/export) or CJS (require). You do not configure anything. It reads your package.json for the "type" field and respects it.
Watch mode restarts your script when files change:
npx tsx --watch src/server.tsThe watch mode uses Node.js's built-in file watcher, which is more reliable and uses fewer resources than older polling-based approaches.
How ts-node Works
ts-node registers a hook into Node.js's module resolution system. When Node.js tries to load a .ts file, ts-node intercepts it, compiles it with the TypeScript compiler, and passes the JavaScript result to Node.js. Every file goes through a full compilation step.
Install ts-node alongside typescript and run a file:
npm install --save-dev ts-node typescript
npx ts-node src/server.tsBy default, ts-node compiles to CommonJS. To use ESM, you need to pass the --esm flag and configure your tsconfig.json with module settings like "nodenext" or "esnext". ESM support works but requires more setup than tsx.
Speed Comparison
The performance difference comes from the transpilation engine. tsx uses esbuild, which processes TypeScript at hundreds of megabytes per second. ts-node uses the TypeScript compiler, which does full type analysis on every file.
Here is a rough comparison for a typical project:
| Scenario | tsx | ts-node |
|---|---|---|
| Start a 50-file project | Under 200ms | 1 to 3 seconds |
| Start a 500-file project | Under 500ms | 5 to 15 seconds |
| File change restart (watch) | Under 100ms | 1 to 4 seconds |
The gap widens as the project grows. For a large monorepo, ts-node can take tens of seconds just to start. tsx stays fast because esbuild does no type analysis.
When to Use tsx
tsx is the right choice for most development tasks. Use it for running build scripts, database seeders, and migration scripts. Use it for starting dev servers where you want fast restarts on file changes. Most modern test runners, including Vitest, use tsx internally.
If your test runner already uses tsx, using it for your scripts keeps your tooling consistent across the entire project. See Test TypeScript Code with Vitest for setting up a test runner that uses tsx.
When to Use ts-node
ts-node is worth keeping when you need one of its specific features. Use it if you want type checking to happen during execution itself, so the script fails immediately when types do not match. Use it if your project relies on custom TypeScript transformers that only ts-node supports.
For most new projects, these features are unnecessary. You can run a separate type-check step in your workflow for correctness, and you rarely need custom transformers.
The Recommended Combination
A common pattern combines tsx for speed with a separate type-check step for correctness:
{
"scripts": {
"dev": "tsx --watch src/server.ts",
"typecheck": "tsc --noEmit",
"lint": "eslint ."
}
}This gives you fast restarts during development and type safety in CI. The two concerns are separated: tsx handles execution speed, and the compiler handles correctness. For understanding all the pieces of a modern TypeScript toolchain, see TypeScript compiler explained.
Rune AI
Key Insights
- tsx uses esbuild under the hood, making it significantly faster than ts-node for startup.
- tsx handles ESM and CJS modules natively with zero configuration.
- ts-node supports type checking during execution and custom transformers; tsx does neither.
- Both tools offer watch mode, but tsx uses Node.js native file watching for better reliability.
- For most development workflows, choose tsx. Keep ts-node only if you need its specific features.
Frequently Asked Questions
Can tsx replace ts-node completely?
Does tsx type-check my code?
Is tsx production-ready?
Conclusion
tsx is the simpler, faster choice for most TypeScript development workflows. ts-node still has a place when you need type checking during execution or custom transformers. For running scripts, dev servers, and tests, install tsx and move on.
More in this topic
TypeScript Compiler Explained
The TypeScript compiler (tsc) turns .ts files into .js files while checking types. Learn what it does, how to use it, and how it fits your workflow.
Set Up ESLint for TypeScript
Install and configure ESLint with typescript-eslint to catch bugs and enforce consistent code style in your TypeScript project.
Pick Utility Type in TypeScript
Pick creates a new type by selecting only the properties you name from an existing type. Use it to build focused types for specific views, API responses, or function parameters.