ts-directly
raw JSON → 2.1.2 verified Fri May 01 auth: no javascript
TS-Directly (v2.1.2) is a lightweight ESM loader that lets Node.js execute TypeScript files directly using the compiler already installed in the project (SWC, esbuild, sucrase, or tsc). It features automatic compiler detection (preferring the fastest), respects closest tsconfig.json including baseUrl/paths aliases, supports .cts/.mts files and ESNext module output, and exposes a transform API. Unlike ts-node or tsx it does not bundle a compiler, making it ideal for CLI tools that want to reuse existing dependencies. Released monthly on npm, actively maintained with 5 KB minified size and zero extra dependency beyond node loaders.
Common errors
error No TypeScript compiler found ↓
cause No supported compiler installed in the project.
fix
Install one of: @swc/core, esbuild, sucrase, or typescript as a dependency.
error ERR_REQUIRE_ESM ↓
cause Using require() on an ESM-only package (ts-directly is ESM-only since v2.0.0).
fix
Use import statements or dynamic import(). If you must use CommonJS, downgrade to v1.x.
error Invalid TS_COMPILER environment variable: 'some-value' ↓
cause The TS_COMPILER env var is set to an unsupported value.
fix
Set TS_COMPILER to one of: 'swc', 'esbuild', 'sucrase', 'tsc' (case-insensitive).
Warnings
breaking detectTypeScriptCompiler export removed in v2.0.0 ↓
fix Use the automatic detection or switch to transform() which internally detects the compiler.
breaking ESM-only: require() will throw ERR_REQUIRE_ESM since v2.0.0 ↓
fix Use import statements or dynamic import() instead of require().
gotcha Compiler must be installed separately; missing compiler causes runtime error: 'No TypeScript compiler found' ↓
fix Install one of: @swc/core, esbuild, sucrase, or typescript. If multiple are present, the fastest (esbuild > sucrase > swc > tsc) is chosen.
gotcha Paths alias only works for import/require, not for directory indexes or extension-less requires ↓
fix Always use full file paths with extensions for aliased imports, or avoid alias for directory resolution.
gotcha Single file transform does not handle module resolution; for full ESM loader use --import ts-directly/register ↓
fix Use the loader registration if you need import resolution (e.g., .js -> .ts redirection), not just transform().
Install
npm install ts-directly yarn add ts-directly pnpm add ts-directly Imports
- transform wrong
const { transform } = require('ts-directly')correctimport { transform } from 'ts-directly' - register wrong
require('ts-directly/register')correctmodule.register('ts-directly', import.meta.url) - default export wrong
require('ts-directly/register')correctimport 'ts-directly/register'
Quickstart
// Install: pnpm add ts-directly
// Ensure at least one compiler is installed, e.g., typescript: pnpm add typescript
// File: main.ts
import { readFileSync } from 'fs';
import { transform } from 'ts-directly';
const tsCode = readFileSync('example.ts', 'utf8');
transform(tsCode, 'example.ts')
.then(({ source, format }) => {
console.log(format); // 'module' or 'commonjs'
console.log(source.substring(0, 100)); // preview
});
// Or run directly with Node:
// node --import ts-directly/register main.ts