Node.js integration
This guide details how to integrate tsx
with Node.js, allowing you to enhance Node.js with TypeScript support without directly running tsx
. Because Node.js offers Module and CommonJS contexts, you can opt into enhancing them selectively.
This setup is useful for running binaries with TypeScript support, developing packages that load TypeScript files, or direct usage of node
.
Only TypeScript & ESM support
When using the Node.js integrations, CLI features such as Watch mode will not be available.
Module & CommonJS enhancement
Command-line API
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
Node.js also allows you to pass in command-line flags via the NODE_OPTIONS
environment variable:
NODE_OPTIONS='--import tsx' node ./file.ts
This means you can also add tsx to binaries to add TypeScript support:
NODE_OPTIONS='--import tsx' npx eslint
Node.js API
Add this at the top of your entry-file:
import 'tsx'
Only Module enhancement
For situations where you need TypeScript support only in a Module context (using
.mjs
files orpackage.json
with"type": "module"
).
Command-line API
# Node.js v20.6.0 and above
node --import tsx/esm ./file.ts
# Node.js v20.5.1 and below
node --loader tsx/esm ./file.ts
Registration & Unregistration
import { register } from 'tsx/esm/api'
// register tsx enhancement
const unregister = register()
// Unregister when needed
unregister()
Tracking loaded files
Detect files that get loaded with the onImport
hook:
register({
onImport: (file: string) => {
console.log(file)
// file:///foo.ts
}
})
Only CommonJS enhancement
For situations where you need TypeScript and ESM support only in a CommonJS context (using
.cjs
files orpackage.json
with"type": "commonjs"
).
Command-line API
Pass tsx into the --require
flag:
node --require tsx/cjs ./file.ts
This is the equivalent of adding the following at the top of your entry file, which you can also do:
require('tsx/cjs')
Registration & Unregistration
To manually register and unregister the tsx enhancement:
const tsx = require('tsx/cjs/api')
// Register tsx enhancement
const unregister = tsx.register()
// Unregister when needed
unregister()
Enhanced import()
& require()
tsx exports enhanced import()
or require()
functions, allowing you to load TypeScript/ESM files without affecting the runtime environment.
tsImport()
The import()
function enhanced to support TypeScript. Because it's the native import()
, it supports top-level await.
Caveat
require()
calls in the loaded files are not enhanced.
ESM usage
Note, the current file path must be passed in as the second argument to resolve the import context.
import { tsImport } from 'tsx/esm/api'
const loaded = await tsImport('./file.ts', import.meta.url)
CommonJS usage
const { tsImport } = require('tsx/esm/api')
const loaded = await tsImport('./file.ts', __filename)
Tracking loaded files
Detect files that get loaded with the onImport
hook:
tsImport('./file.ts', {
parentURL: import.meta.url,
onImport: (file: string) => {
console.log(file)
// file:///foo.ts
}
})
tsx.require()
The require()
function enhanced to support TypeScript and ESM.
Caveat
import()
& asynchronous require()
calls in the loaded files are not enhanced.
CommonJS usage
Note, the current file path must be passed in as the second argument to resolve the import context.
const tsx = require('tsx/cjs/api')
const loaded = tsx.require('./file.ts', __filename)
const filepath = tsx.require.resolve('./file.ts', __filename)
ESM usage
import { require } from 'tsx/cjs/api'
const loaded = require('./file.ts', import.meta.url)
const filepath = require.resolve('./file.ts', import.meta.url)
Tracking loaded files
Because the CommonJS API tracks loaded modules in require.cache
, you can use it to identify loaded files for dependency tracking. This can be useful when implementing a watcher.
const resolvedPath = tsx.require.resolve('./file', import.meta.url)
const collectDependencies = module => [
module.filename,
...module.children.flatMap(collectDependencies)
]
console.log(collectDependencies(tsx.require.cache[resolvedPath]))
// ['/file.ts', '/foo.ts', '/bar.ts']