TypeScript Execute (
tsx
): Node.js enhanced to run TypeScript & ESM files
- Blazing fast on-demand TypeScript & ESM compilation
- Works in both CommonJS and ESM packages
- Supports next-gen TypeScript extensions (
.cts
&.mts
) - Hides experimental feature warnings
- TypeScript REPL
- Resolves
tsconfig.json
paths
Tip
Do you need to compile your TypeScript projects? Try pkgroll—the zero-config bundler tsx uses!
pkgroll is a thin layer over Rollup that auto-configures it based on your package.json
entry points.
It supports next-gen TS formats, export maps, .d.ts
generation, and more!
tsx
is a CLI command (alternative to node
) for seamlessly running TypeScript & ESM in both commonjs
& module
package types.
This is for you if you ever wanted:
- A command that can just run TypeScript code without dealing with configuration
- Better interoperability in codebases that use ESM and CJS dependencies
- Something really fast it's unnoticeable!
Tip
tsx is not just for TypeScript! It also helps Node load module
type packages.
If you're getting the following error, give tsx a try!
require('ESM package');
^
Error [ERR_REQUIRE_ESM]: require() of ES Module <ESM package> from ./file.js not supported.
Instead change the require of <ESM package> in ./file.js to a dynamic import() which is available in all CommonJS modules.
Try tsx now without setup! Just pass in a TypeScript file:
npx tsx ./script.ts
- Enhance Node.js with TypeScript support
- Improve ESM <-> CJS interoperability as the ecosystem migrates to ESM
- Support the LTS versions of Node.js
If you're using it in an npm project, install it as a development dependency:
npm install --save-dev tsx
Then you can reference it directly in the package.json#scripts
object (you don't need npx here):
{
"scripts": {
"dev": "tsx ..."
}
}
To use the binary, you can call it with npx
while in the project directory:
npx tsx ...
If you want to use it in any arbitrary project without npx
, install it globally:
npm install --global tsx
Then, you can call tsx
directly:
tsx ...
tsx wraps around Node.js to enhance it with TypeScript support. Because it's a drop-in replacement for node
, it supports all Node.js command-line flags.
# --no-warnings is a Node.js flag
tsx --no-warnings ./file.ts
Pass in a file to run:
tsx ./file.ts
By default, tsconfig.json
will be detected from the current working directory.
To set a custom path, use the --tsconfig
flag:
tsx --tsconfig ./path/to/tsconfig.custom.json ./file.ts
Alternatively, use the TSX_TSCONFIG_PATH
environment variable:
TSX_TSCONFIG_PATH=./path/to/tsconfig.custom.json tsx ./file.ts
Run file and automatically rerun on changes:
tsx watch ./file.ts
All imported files are watched except from the following directories:
node_modules
, bower_components
, vendor
, dist
, and .*
(hidden directories).
To exclude files from being watched, pass in a path or glob to the --ignore
flag:
tsx watch --ignore ./ignore-me.js --ignore ./ignore-me-too.js ./file.ts
- Press Return to manually rerun
- Pass in
--clear-screen=false
to disable clearing the screen on rerun
Start a TypeScript REPL by running with no arguments:
tsx
Modules transformations are cached in the system cache directory (TMPDIR
). Transforms are cached by content hash, so duplicate dependencies are not re-transformed.
Set the --no-cache
flag to disable the cache:
tsx --no-cache ./file.ts
Alternatively, use the TSX_DISABLE_CACHE
environment variable:
TSX_DISABLE_CACHE=1 tsx ./file.ts
tsx
is a standalone binary designed to be used in place of node
, but sometimes you'll want to use node
directly. For example, when adding TypeScript & ESM support to npm-installed binaries.
To use tsx
as a Node.js loader, pass it in to the --import
flag. This will add TypeScript & ESM support for both Module and CommonJS contexts.
node --import tsx ./file.ts
Or as an environment variable:
NODE_OPTIONS='--import tsx' node ./file.ts
Note: The loader is limited to adding support for loading TypeScript/ESM files. CLI features such as watch mode or suppressing "experimental feature" warnings will not be available.
If you only need to add TypeScript support in a Module context, you can use the ESM loader:
node --import tsx/esm ./file.ts
node --loader tsx/esm ./file.ts
If you only need to add TypeScript & ESM support in a CommonJS context, you can use the CJS loader:
node --require tsx/cjs ./file.ts
If you prefer to write scripts that doesn't need to be passed into tsx, you can declare it in the hashbang.
Simply add #!/usr/bin/env tsx
at the top of your file:
file.ts
#!/usr/bin/env tsx
console.log('argv:', process.argv.slice(2))
And make the file executable:
chmod +x ./file.ts
Now, you can run the file without passing it into tsx:
$ ./file.ts hello
argv: [ 'hello' ]
Create the following configuration file in your project to setup debugging in VS Code:
.vscode/launch.json
{
"version": "0.2.0",
"configurations": [
/*
Each config in this array is an option in the debug drop-down
See below for configurations to add...
*/
],
}
-
Add the following configuration to the
configurations
array in.vscode/launch.json
:{ "name": "tsx", "type": "node", "request": "launch", // Debug current file in VSCode "program": "${file}", /* Path to tsx binary Assuming locally installed */ "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/tsx", /* Open terminal when debugging starts (Optional) Useful to see console.logs */ "console": "integratedTerminal", "internalConsoleOptions": "neverOpen", // Files to exclude from debugger (e.g. call stack) "skipFiles": [ // Node.js internal core modules "<node_internals>/**", // Ignore all dependencies (optional) "${workspaceFolder}/node_modules/**", ], }
-
In VSCode, open the file you want to run
-
Go to VSCode's debug panel, select "tsx" in the drop down, and hit the play button (F5).
This method works for any Node.js process and it's not specific to tsx
-
Add the following configuration to the
configurations
array in.vscode/launch.json
:{ "name": "Attach to process", "type": "node", "request": "attach", "port": 9229, "skipFiles": [ // Node.js internal core modules "<node_internals>/**", // Ignore all dependencies (optional) "${workspaceFolder}/node_modules/**", ], }
-
Run tsx with
--inspect-brk
in a terminal window:tsx --inspect-brk ./your-file.ts
-
Go to VSCode's debug panel, select "Attach to process" in the drop down, and hit the play button (F5).
See the VSCode documentation on Launch Configuration for more information.
If there's a problem you're encountering or something you need help with, don't hesitate to take advantage of my Priority Support service where you can ask me questions in an exclusive forum. I'm well equppied to assist you with this project and would be happy to help you out! 🙂
tsx
stands for "TypeScript execute". Mirroring npx
, which stands for "Node.js package execute".
The 3-character package name offers an elegant developer experience, allowing usage like: npx tsx ...
.
Unfortunately, it overlaps with React's TSX/JSX, which stands for "TypeScript XML".
No. tsx is designed to be a simple TypeScript runner.
If you need type-checking, you can use an IDE like VS Code and it will type-check as you code via IntelliSense. Alternatively, you can run the TypeScript Compiler only for type-checking (e.g. tsc --noEmit
) as a linting step.
How is tsx
different from ts-node
?
They're both tools to run TypeScript files. But tsx does a lot more to improve the experience of using Node.js.
tsx just works. It's zero-config and doesn't require tsconfig.json
to get started, making it easy for users that just want to run TypeScript code and not get caught up in the configuration.
It's a single binary with no peer-dependencies (e.g. TypeScript or esbuild), so there is no setup necessary, enabling usage that is elegant and frictionless for first-time users:
npx tsx ./script.ts
tsx is zero-config because it has smart detections built in. As a runtime, it detects what's imported to make many options in tsconfig.json
redundant—which was designed for compiling matching files regardless of whether they're imported.
It seamlessly adapts between CommonJS and ESM package types by detecting how modules are loaded (require()
or import
) to determine how to compile them. It even adds support for require()
ing ESM modules from CommonJS so you don't have to worry about your dependencies as the ecosystem migrates to ESM.
Newer and unsupported syntax & features like importing node:
prefixes are downgraded by detecting the Node.js version. For large TypeScript codebases, it has tsconfig.json paths
aliasing support out of the box.
At the core, tsx is powered by esbuild for blazing fast TypeScript compilation, whereas ts-node
(by default) uses the TypeScript compiler. Because esbuild doesn't type check, tsx
is similar to ts-node --esm --swc
(which uses the SWC compiler).
As a bonus, tsx also comes with a watcher to speed up your development.
Here's an exhaustive technical comparison between tsx
, ts-node
, and other runtimes.
No. tsx's integration with Node.js is designed to be simple & seamless. However, it supports a few properties from tsconfig.json
to determine how to compile TypeScript files.
TypeScript & ESM transformations are handled by esbuild, so it shares the same limitations such as:
- Compatibility with code executed via
eval()
is not preserved - Only certain
tsconfig.json
properties are supported emitDecoratorMetadata
is not supported
For details, refer to esbuild's JavaScript caveats and TypeScript caveats documentation.