Файл TypeScript нельзя запустить как есть, потому что браузеры и движки JavaScript не понимают аннотаций типов. Сначала кто-то должен удалить типы. Это либо компилятор TypeScript (tsc), который заодно проверяет типы, либо более быстрый инструмент, который только их удаляет. Быстрее всего запустить код на этой странице кнопкой Run:
Вывод:
[x] Install TypeScript
[ ] Run a .ts file
Все запускаемые блоки в этой документации работают одинаково: TypeScript 7 проверяет код с включённым strict, и код запускается, только если ошибок типов нет. Для экспериментов подлиннее есть песочница TypeScript, тот же редактор на отдельной странице. Остальная часть страницы посвящена запуску файлов .ts на вашем компьютере.
Варианты коротко
| Команда | Проверяет типы | Нужен этап сборки | Поддерживает enum, namespace, свойства-параметры |
|---|---|---|---|
npx tsc, затем node dist/index.js | Да | Да | Да |
node index.ts (Node.js 22.18+, 23.6+) | Нет | Нет | Нет |
npx tsx index.ts | Нет | Нет | Да |
npx ts-node index.ts | Да | Нет | Да, но не с TypeScript 7 |
deno run index.ts | Нет (это делает deno check) | Нет | Да |
bun index.ts | Нет | Нет | Да |
Удивляет обычно первый столбец: большинство быстрых вариантов запускают код, в котором есть ошибки типов. Типичный проект запускает код одним из них, а tsc --noEmit выполняет отдельно, в редакторе и в CI, чтобы ловить ошибки.
Компиляция через tsc и запуск через Node
Этот подход работает везде и проверяет всё. Если TypeScript установлен в проекте, а tsconfig.json задаёт "rootDir": "./src" и "outDir": "./dist":
npx tsc
node dist/index.js
tsc проверяет типы во всех файлах, затем записывает файлы .js в dist. Для одного файла без проекта передайте имя файла. Тогда используются параметры по умолчанию, а index.js записывается рядом с index.ts:
npx tsc index.ts
node index.js
(Если в папке есть tsconfig.json, tsc отказывается принимать имена файлов с ошибкой error TS5112; выполните просто npx tsc или добавьте --ignoreConfig.)
По умолчанию tsc записывает JavaScript даже при ошибках типов, так что node может запустить программу, которая не прошла проверку. Добавьте в конфигурацию "noEmitOnError": true, чтобы этого не было, или объедините команды в скрипте, чтобы второй шаг выполнялся только при успехе первого:
{
"scripts": {
"build": "tsc",
"start": "tsc && node dist/index.js"
}
}
Во время разработки npx tsc --watch перекомпилирует код при каждом сохранении.
Запуск TypeScript напрямую в Node.js
Современный Node.js сам запускает файлы .ts:
node index.ts
Node удаляет аннотации типов, заменяя их пробелами, чтобы номера строк в трассировках стека совпадали, и запускает оставшееся. Это включено по умолчанию начиная с Node.js 23.6.0 и 22.18.0, без предупреждения начиная с 24.3.0 и 22.18.0, а стабильной эта возможность стала в Node.js 24.12.0 и 25.2.0. Более ранним выпускам с этой возможностью (от 22.6 до 22.17 и от 23.0 до 23.5) нужен флаг: node --experimental-strip-types index.ts.
С этим связаны четыре правила:
- Нет проверки типов. Файл с
const age: number = "forty"запустится и напечатаетforty. - Только стираемый синтаксис. Всё, что должно превратиться в код JavaScript, а не исчезнуть, отвергается:
enum, блокиnamespaceс кодом времени выполнения, свойства-параметры конструктора вродеconstructor(private name: string)и псевдонимыimport x = require(). Node останавливается сSyntaxError [ERR_UNSUPPORTED_TYPESCRIPT_SYNTAX]: TypeScript enum is not supported in strip-only mode. tsconfig.jsonигнорируется. Параметры вродеpathsилиtargetни на что не влияют.- В импортах нужны настоящие имена файлов. Пишите
import { add } from "./math.ts"с расширением и помечайте импорты только типов черезtype:import { add, type Pair } from "./math.ts". БезtypeNode ищет экспорт времени выполнения с именемPairи падает сSyntaxError: The requested module './math.ts' does not provide an export named 'Pair'.
Два параметра компилятора заставляют tsc соблюдать те же правила, так что редактор предупредит вас раньше Node: "erasableSyntaxOnly": true сообщает error TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled. на enum, а "verbatimModuleSyntax": true требует ключевое слово type в импортах только типов. Чтобы писать расширения .ts в импортах и при этом компилировать через tsc, добавьте "rewriteRelativeImportExtensions": true: он превращает ./math.ts в ./math.js в выходных файлах.
В Node.js 24 есть также --experimental-transform-types, который генерирует код для enum и свойств-параметров, а не отвергает их. Он выводит ExperimentalWarning, а в Node.js 26 этот флаг удалён, так что не стройте на нём ничего.
В этом блоке используются две возможности, которые node index.ts отвергает. Здесь он работает, потому что редактор компилирует его компилятором TypeScript, который генерирует JavaScript для обеих:
Стираемая версия того же кода использует объект const и обычное поле, и Node может запустить её как есть:
tsx
tsx запускает файл TypeScript за один шаг, без настройки и без ограничений на синтаксис:
npm install --save-dev tsx
npx tsx index.ts
npx tsx watch index.ts # rerun on every change
Он преобразует код через esbuild, поэтому enum, пространства имён и свойства-параметры работают, а импорты без расширений разрешаются так же, как в бандлере. Как и удаление типов в Node, он не проверяет типы. Это обычный выбор для скриптов, dev-серверов и тестов на версиях Node.js, выпущенных до появления удаления типов, или когда код использует синтаксис, который Node отвергает.
ts-node
ts-node годами был стандартным способом запускать TypeScript в Node.js, и многие руководства и старые проекты до сих пор используют его (npx ts-node index.ts, node -r ts-node/register). По умолчанию он проверяет типы через JavaScript API компилятора TypeScript.
Именно этого API в TypeScript 7 нет: его компилятор это нативная программа, и пакет typescript 7 не предоставляет JavaScript никакого API компилятора. С установленным TypeScript 7 ts-node падает, ничего не запустив:
TypeError: Cannot read properties of undefined (reading 'fileExists')
at readConfig (/project/node_modules/ts-node/dist/configuration.js:91:33)
Последний релиз ts-node, 10.9.2, вышел в декабре 2023 года. Для нового кода используйте tsx или node index.ts. Существующая конфигурация, зависящая от ts-node, продолжает работать, если проект остаётся на TypeScript 6 (npm install --save-dev typescript@6) и у него есть tsconfig.json, пусть даже пустой {}. Без него ts-node использует встроенные значения по умолчанию, включая разрешение модулей node10, которое в TypeScript 6 объявлено устаревшим, и npx ts-node index.ts завершается, не запустив файл и не выведя ошибки.
Deno и Bun
Обе среды выполнения считают TypeScript полноценным типом файлов:
deno run index.ts # runs without checking
deno check index.ts # type-checks, reports errors, runs nothing
bun index.ts # runs without checking
Ни одной из них не нужны установленный typescript или tsconfig.json, и обе поддерживают enum и другие нестираемые возможности. Deno поставляет собственную копию компилятора TypeScript для deno check. Bun только удаляет типы, поэтому в проекте на Bun всё равно устанавливают typescript и запускают tsc --noEmit, чтобы находить ошибки типов.
Ошибки типов останавливают программу только в tsc
Только способы, которые сначала запускают tsc, отказываются запускать программу с ошибками типов. Редактор на этой странице один из них, поэтому этот блок останавливается на компиляторе:
index.ts(6,21): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
Если сохранить этот код в файл и запустить через node index.ts, npx tsx index.ts или bun index.ts, он выполнится и напечатает 12, потому что 3 * "4" преобразует строку. Поэтому tsc --noEmit стоит держать в процессе, даже если код запускает более быстрый инструмент:
{
"scripts": {
"dev": "tsx watch src/index.ts",
"typecheck": "tsc --noEmit"
}
}
Что выбрать?
- Обучение или быстрая проверка: кнопка Run на этих страницах или песочница.
- Скрипт или небольшая утилита на современном Node.js:
node index.ts, сerasableSyntaxOnlyв конфигурации, чтобы редактор отмечал всё, что Node отвергнет. - Любой проект на Node.js с любым синтаксисом:
tsxдля запуска,tsc --noEmitдля проверки. - Библиотека или всё, что вы публикуете:
tsc, потому что он ещё и записывает файлы.d.ts, нужные вашим пользователям. - Фронтенд-код: ваш бандлер или фреймворк (Vite, Next.js, Angular CLI) запускает TypeScript за вас; добавьте
tsc --noEmitдля проверки.
Часто задаваемые вопросы
Как запустить файл TypeScript?
Классический способ состоит из двух шагов: npx tsc компилирует .ts в .js, затем node dist/index.js запускает результат. В Node.js 22.18 или 23.6 и новее можно также запустить node index.ts напрямую, если файл использует только синтаксис типов, который можно стереть. npx tsx index.ts запускает любой файл TypeScript за один шаг.
Может ли Node.js запускать TypeScript напрямую?
Да. Начиная с Node.js 23.6 и 22.18 node file.ts работает без флагов: Node удаляет аннотации типов и запускает остальное. Он не проверяет типы, игнорирует tsconfig.json и отвергает синтаксис, которому нужна генерация кода, например enum, namespace с кодом времени выполнения и свойства-параметры конструктора.
Работает ли ts-node с TypeScript 7?
Нет. ts-node вызывает JavaScript API компилятора, которого нет в пакете typescript 7, поэтому он падает при запуске (Cannot read properties of undefined (reading 'fileExists')). Его последний релиз 10.9.2 вышел в декабре 2023 года. Используйте tsx, встроенное удаление типов в Node или оставьте ts-node с TypeScript 6.
Чем tsx отличается от ts-node?
tsx только удаляет типы (через esbuild) и запускает результат, поэтому стартует быстро и никогда не сообщает об ошибках типов. ts-node по умолчанию проверяет типы компилятором TypeScript, поэтому работает медленнее и зависит от JavaScript API компилятора. Большинство проектов сейчас запускают код через tsx или node file.ts, а проверяют через tsc --noEmit.
Есть ли онлайн-песочница для TypeScript?
Да. Блоки кода на этих страницах документации и песочница TypeScript на Coddy компилируют ваш код через TypeScript 7 и запускают его, показывая ошибки компилятора или вывод программы. Официальный TypeScript Playground на typescriptlang.org показывает сгенерированный JavaScript и ошибки.