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.

5 min read

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-nodetsx
EngineTypeScript compiler (tsc)esbuild
Startup speedSlowerMuch faster
Type checking during runYesNo
ESM supportRequires configurationAutomatic
CJS supportNativeNative
Watch modeBuilt-inBuilt-in (Node.js watcher)
REPLYesYes
Custom transformersYesNo

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:

bashbash
npm install --save-dev tsx
npx tsx src/server.ts

tsx 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:

bashbash
npx tsx --watch src/server.ts

The 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:

bashbash
npm install --save-dev ts-node typescript
npx ts-node src/server.ts

By 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:

Scenariotsxts-node
Start a 50-file projectUnder 200ms1 to 3 seconds
Start a 500-file projectUnder 500ms5 to 15 seconds
File change restart (watch)Under 100ms1 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.

A common pattern combines tsx for speed with a separate type-check step for correctness:

jsonjson
{
  "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

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.
RunePowered by Rune AI

Frequently Asked Questions

Can tsx replace ts-node completely?

For most projects, yes. tsx handles everything ts-node does: running scripts, watch mode, and REPL. The main reason to keep ts-node is if you rely on a feature tsx does not support, such as custom transformers or type checking during execution.

Does tsx type-check my code?

No. tsx strips types and runs the resulting JavaScript. It does not run the TypeScript compiler. For type checking, run tsc --noEmit separately in your workflow.

Is tsx production-ready?

tsx is designed for development workflows: running scripts, dev servers, and tests. For production, compile your TypeScript with tsc and run the JavaScript output directly.

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.