tsx для TypeScript: полное руководство с примерами
1. Что это и зачем нужна
tsx — это современный, высокопроизводительный раннер для TypeScript и ESM (ECMAScript Modules), который позволяет запускать файлы .ts, .tsx и .mts напрямую, без предварительной компиляции в JavaScript. Разработанный на основе esbuild (сверхбыстрого бандлера на Go), tsx обеспечивает практически мгновенный запуск TypeScript-кода, что делает его идеальным инструментом для разработки, прототипирования, написания скриптов и тестирования.
Зачем нужна tsx? Традиционно для запуска TypeScript-файлов требуется двухэтапный процесс: сначала скомпилировать код с помощью tsc (TypeScript Compiler), а затем выполнить полученный JavaScript через Node.js. Это замедляет итерации разработки. tsx решает эту проблему, объединяя компиляцию и выполнение в один шаг. Он автоматически обрабатывает TypeScript-синтаксис, модули ESM, JSX и даже поддерживает node_modules resolution. По сути, tsx — это замена ts-node, но значительно более быстрая и современная.
Ключевые преимущества tsx перед аналогами: скорость (использует esbuild, который в 10-100 раз быстрее tsc), поддержка ESM из коробки (без необходимости настройки tsconfig.json для модулей), автоматическое обнаружение конфигурации TypeScript, и встроенная поддержка --watch режима. tsx идеально подходит для: написания CLI-утилит на TypeScript, запуска тестов (Jest, Vitest), создания скриптов автоматизации, быстрого прототипирования и обучения TypeScript.
2. Установка
tsx распространяется через npm (Node Package Manager) и может быть установлен глобально или локально в проект. Рекомендуется локальная установка для изоляции зависимостей проекта.
Локальная установка (рекомендуется):
npm install --save-dev tsx
Или с использованием yarn:
yarn add --dev tsx
Или pnpm:
pnpm add --save-dev tsx
Глобальная установка (для быстрого доступа из любого места):
npm install -g tsx
Проверка установки:
npx tsx --version
После установки вы можете запускать TypeScript-файлы командой npx tsx имя_файла.ts (при локальной установке) или tsx имя_файла.ts (при глобальной).
Важно: tsx требует Node.js версии 18 или выше. Для работы с ESM убедитесь, что в вашем package.json есть поле "type": "module" или используйте расширение .mts для файлов.
3. Быстрый старт — минимальный рабочий пример
Создайте файл hello.ts со следующим содержимым:
// hello.ts
const greet = (name: string): string => {
return `Привет, ${name}! Добро пожаловать в мир tsx!`;
};
const userName: string = "PythonLib";
console.log(greet(userName));
// Использование современных возможностей JS
const numbers: number[] = [1, 2, 3, 4, 5];
const doubled = numbers.map((n) => n * 2);
console.log("Удвоенные числа:", doubled);
// Асинхронный код
const fetchData = async (): Promise => {
const data = await Promise.resolve({ id: 1, name: "Пример" });
console.log("Асинхронные данные:", data);
};
fetchData();
Запустите файл командой:
npx tsx hello.ts
Ожидаемый вывод:
Привет, PythonLib! Добро пожаловать в мир tsx!
Удвоенные числа: [ 2, 4, 6, 8, 10 ]
Асинхронные данные: { id: 1, name: 'Пример' }
Этот пример демонстрирует базовую работу tsx: он автоматически компилирует TypeScript в JavaScript, поддерживает стрелочные функции, типизацию, массивы и асинхронный код — всё без предварительной настройки.
4. Основные методы/функции/классы
tsx — это не библиотека с API в традиционном смысле, а CLI-инструмент (Command Line Interface). Однако у него есть ряд ключевых команд и опций, которые можно рассматривать как "методы". Ниже приведены 8 основных способов использования tsx.
4.1. Запуск файла: tsx [файл]
Сигнатура: tsx [options] <file> [args...]
Что делает: Компилирует и выполняет указанный TypeScript-файл. Можно передавать аргументы командной строки, которые будут доступны через process.argv.
// args-example.ts
const args = process.argv.slice(2);
console.log("Переданные аргументы:", args);
if (args.length > 0) {
console.log(`Привет, ${args[0]}!`);
} else {
console.log("Аргументы не переданы.");
}
Запуск: npx tsx args-example.ts Мир TypeScript
Вывод: Переданные аргументы: [ 'Мир', 'TypeScript' ] и Привет, Мир!
4.2. Режим наблюдения: tsx --watch [файл]
Сигнатура: tsx --watch [options] <file>
Что делает: Запускает файл и автоматически перезапускает его при любых изменениях в файле или его зависимостях. Идеально для разработки.
// watch-example.ts
let counter = 0;
setInterval(() => {
counter++;
console.log(`Прошло ${counter} секунд...`);
}, 1000);
Запуск: npx tsx --watch watch-example.ts. При изменении файла процесс автоматически перезапустится.
4.3. Оценка кода: tsx -e "код"
Сигнатура: tsx -e "<code>" или tsx --eval "<code>"
Что делает: Выполняет переданную строку как TypeScript-код без создания файла. Полезно для быстрых проверок.
npx tsx -e "
const add = (a: number, b: number): number => a + b;
console.log('Сумма 5 и 3:', add(5, 3));
"
Вывод: Сумма 5 и 3: 8
4.4. Запуск с указанием конфигурации: tsx --tsconfig [путь]
Сигнатура: tsx --tsconfig <path/to/tsconfig.json> [файл]
Что делает: Позволяет указать кастомный файл конфигурации TypeScript. По умолчанию tsx ищет tsconfig.json в текущей директории.
// custom-config.ts
interface Config {
apiUrl: string;
port: number;
}
const config: Config = {
apiUrl: "https://api.example.com",
port: 3000
};
console.log("Конфигурация загружена:", config);
Запуск: npx tsx --tsconfig ./configs/tsconfig.json custom-config.ts
4.5. Запуск с флагом --no-warnings
Сигнатура: tsx --no-warnings [файл]
Что делает: Подавляет вывод предупреждений Node.js (например, экспериментальные предупреждения). Полезно для чистого вывода.
// no-warnings.ts
console.log("Этот вывод будет без предупреждений Node.js");
Запуск: npx tsx --no-warnings no-warnings.ts
4.6. Запуск с флагом --inspect (отладка)
Сигнатура: tsx --inspect [файл] или tsx --inspect-brk [файл]
Что делает: Запускает файл в режиме отладки, позволяя подключиться к нему через Chrome DevTools или VS Code. --inspect-brk ставит точку остановки на первой строке.
// debug-example.ts
function calculate(x: number, y: number): number {
const result = x * y + 10;
return result;
}
const value = calculate(5, 3);
console.log("Результат:", value);
Запуск: npx tsx --inspect-brk debug-example.ts. Затем откройте chrome://inspect в браузере.
4.7. Запуск с флагом --env-file
Сигнатура: tsx --env-file <path/to/.env> [файл]
Что делает: Загружает переменные окружения из указанного файла перед выполнением скрипта. Аналог dotenv, но встроенный.
// env-example.ts
console.log("API_KEY:", process.env.API_KEY);
console.log("DB_HOST:", process.env.DB_HOST);
Создайте файл .env:
API_KEY=secret-key-123
DB_HOST=localhost:5432
Запуск: npx tsx --env-file .env env-example.ts
Вывод: API_KEY: secret-key-123 и DB_HOST: localhost:5432
4.8. Запуск с флагом --experimental-loader (кастомные лоадеры)
Сигнатура: tsx --experimental-loader <module> [файл]
Что делает: Позволяет подключать кастомные загрузчики модулей (например, для поддержки CSS или JSON импортов). Расширяет возможности tsx.
// loader-example.ts
import data from './data.json' assert { type: 'json' };
console.log("Загруженные данные:", data);
Создайте data.json:
{"name": "tsx", "version": "4.0.0"}
Запуск: npx tsx --experimental-loader ./custom-loader.mjs loader-example.ts (где custom-loader.mjs — ваш кастомный лоадер).
5. Реальный практический пример (100-200 строк кода)
Создадим CLI-утилиту для анализа логов веб-сервера. Она будет читать файл логов, парсить его и выводить статистику по HTTP-методам и статус-кодам.
// log-analyzer.ts
import * as fs from 'fs';
import * as readline from 'readline';
import { performance } from 'perf_hooks';
// Типы данных
interface LogEntry {
ip: string;
timestamp: string;
method: string;
path: string;
statusCode: number;
responseSize: number;
}
interface Stats {
totalRequests: number;
methods: Record;
statusCodes: Record;
averageResponseSize: number;
topPaths: Array<{ path: string; count: number }>;
}
// Функция парсинга строки лога (формат Apache Combined)
function parseLogLine(line: string): LogEntry | null {
const regex = /^(\S+) \S+ \S+ \[([^\]]+)\] "(\S+) (\S+) \S+" (\d{3}) (\d+)/;
const match = line.match(regex);
if (!match) return null;
return {
ip: match[1],
timestamp: match[2],
method: match[3],
path: match[4],
statusCode: parseInt(match[5], 10),
responseSize: parseInt(match[6], 10)
};
}
// Функция анализа логов
async function analyzeLogs(filePath: string): Promise {
const stats: Stats = {
totalRequests: 0,
methods: {},
statusCodes: {},
averageResponseSize: 0,
topPaths: []
};
const pathCount: Record = {};
let totalSize = 0;
const fileStream = fs.createReadStream(filePath);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
for await (const line of rl) {
const entry = parseLogLine(line);
if (!entry) continue;
stats.totalRequests++;
// Счетчик методов
stats.methods[entry.method] = (stats.methods[entry.method] || 0) + 1;
// Счетчик статус-кодов
const statusGroup = `${Math.floor(entry.statusCode / 100)}xx`;
stats.statusCodes[statusGroup] = (stats.statusCodes[statusGroup] || 0) + 1;
// Размер ответа
totalSize += entry.responseSize;
// Пути
pathCount[entry.path] = (pathCount[entry.path] || 0) + 1;
}
// Средний