TypeScript в Node: Практическая настройка
Вы уже пишете на TypeScript для браузера. Теперь вам нужно запустить его на серверной стороне — для API, скрипта сборки или SSR. Проблема: большинство руководств по настройке устарели и рекомендуют конфигурации CommonJS или инструменты, которые не соответствуют современному Node.js.
Это руководство охватывает два подхода к настройке TypeScript в Node.js: компиляция с помощью tsc и запуск JavaScript, или прямой запуск .ts файлов с использованием встроенного удаления типов Node. Оба подхода работают. Каждый подходит для разных сценариев.
Ключевые выводы
- Установите
"type": "module"в package.json для включения ESM по умолчанию в современных проектах TypeScript Node.js - Используйте компиляцию
tscдля production-развертываний, публикуемых пакетов и кода, использующего enums, namespaces или parameter properties - Используйте встроенное удаление типов Node для локальных скриптов, серверов разработки и быстрых прототипов
- Всегда используйте
import typeдля импорта только типов, чтобы избежать ошибок во время выполнения при удалении типов - Запускайте
tsc --noEmitв CI, поскольку удаление типов Node не выполняет проверку типов
Базовая настройка: Node 24 LTS и ESM
Начните с этой основы:
{
"type": "module"
}
Это включает ESM по умолчанию. Ваши импорты используют синтаксис ESM, и Node разрешает модули соответствующим образом.
Node 24 — это текущая базовая версия LTS для этой настройки (можно скачать здесь: https://nodejs.org/en/download).
Подход 1: Компиляция с tsc, запуск JavaScript
Этот подход разделяет компиляцию и выполнение. Используйте его для production-развертываний, публикуемых пакетов или когда вам нужна полная поддержка возможностей TypeScript.
tsconfig для Node 24
{
"compilerOptions": {
"target": "ES2024",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"rootDir": "src",
"outDir": "dist",
"strict": true,
"skipLibCheck": true,
"declaration": true,
"sourceMap": true,
"verbatimModuleSyntax": true,
"isolatedModules": true,
"lib": ["ES2024"]
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}
Ключевые настройки в этой конфигурации:
module: NodeNextиmoduleResolution: NodeNext: Соответствует фактическому поведению разрешения модулей NodeverbatimModuleSyntax: Требует явногоimport typeдля импорта только типов — критически важно для избежания ошибок во время выполнения (см. документацию TypeScript: https://www.typescriptlang.org/tsconfig#verbatimModuleSyntax)isolatedModules: Обеспечивает совместимость с инструментами транспиляции отдельных файлов
Скрипты
{
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "tsc --watch"
}
}
Запустите npm run build, затем npm start. Скомпилированный JavaScript находится в dist/.
Подход 2: Встроенная поддержка TypeScript в Node (удаление типов)
Node представил встроенную поддержку TypeScript в Node 22 и стабилизировал её в Node 24 LTS через удаление типов. Используйте её для скриптов, локальных инструментов или разработки, когда вы хотите избежать этапов сборки.
Официальная документация: https://nodejs.org/api/typescript.html
Как это работает
В Node 24+ запускайте напрямую:
node src/index.ts
(Старые версии Node требовали экспериментальных флагов; Node 24 не требует.)
Критические ограничения
Встроенная поддержка TypeScript в Node только удаляет типы — она не проверяет типы. Вам всё ещё нужен tsc --noEmit в CI или в вашем редакторе для обнаружения ошибок.
Другие ограничения:
- Игнорирует tsconfig.json: Node не читает ваши опции компилятора
- Требует явных расширений файлов: Пишите
import { foo } from './utils.js'даже когда исходный файл —utils.ts - Соблюдает правила ESM и CJS: Поле type в вашем
package.jsonимеет значение - Не запускает TypeScript из node_modules: Зависимости должны быть скомпилированным JavaScript
- Поддерживает только удаляемый синтаксис: Enums, namespaces и parameter properties не работают, если не включить
--experimental-transform-types
Расширения файлов имеют значение
Для смешанных форматов модулей:
.mtsфайлы → всегда ESM.ctsфайлы → всегда CommonJS.tsфайлы → следуют полю type вpackage.json
Discover how at OpenReplay.com.
Избежание ошибок во время выполнения
Используйте import type для импорта только типов:
// Правильно
import type { Request, Response } from 'express'
import express from 'express'
// Неправильно - приведёт к ошибке во время выполнения при удалении типов
import { Request, Response } from 'express'
Включите verbatimModuleSyntax в вашем tsconfig, чтобы отлавливать это во время разработки, даже если Node игнорирует конфигурацию во время выполнения.
Какой подход использовать
Используйте компиляцию tsc для:
- Production-развертываний
- Публикуемых npm-пакетов
- Кода, использующего enums, namespaces или parameter properties
- Проектов, требующих source maps в production
Используйте встроенное удаление типов для:
- Локальных скриптов и инструментов
- Серверов разработки (в паре с
--watch) - Быстрых прототипов
- Сборок разработки SSR
Практическая настройка для разработки
Комбинируйте оба подхода:
{
"scripts": {
"dev": "node --watch src/index.ts",
"typecheck": "tsc --noEmit",
"build": "tsc",
"start": "node dist/index.js"
}
}
Разработка использует встроенное выполнение для скорости. CI запускает typecheck. Production развертывает скомпилированный JavaScript.
Заключение
Современная настройка TypeScript в Node.js проще, чем предполагают старые руководства. Используйте ESM, настройте разрешение модулей NodeNext и выбирайте стратегию выполнения в зависимости от контекста. Встроенное удаление типов работает для разработки и скриптов. Скомпилированный вывод работает для production и пакетов. Оба подхода используют один и тот же исходный код и tsconfig — вы не привязаны ни к одному из них.
Часто задаваемые вопросы
Разрешение модулей Node требует явных расширений файлов для ESM. Когда вы пишете import from ./utils.js, Node ищет именно этот путь во время выполнения, даже если ваш исходный файл — utils.ts. Поскольку удаление типов убирает типы, но не переименовывает файлы, а tsc выводит .js файлы, использование расширений .js в вашем исходном коде гарантирует, что импорты работают в обоих сценариях.
Не по умолчанию. Enums требуют трансформации кода, а не просто удаления типов. Вы можете включить флаг --experimental-transform-types для поддержки enums, namespaces и parameter properties, но это добавляет сложности. Для более простых настроек рассмотрите использование const-объектов с утверждениями as const в качестве альтернативы enums.
Для большинства случаев использования — нет. Встроенное удаление типов Node 24 обрабатывает прямое выполнение .ts. Инструменты вроде ts-node и tsx — это опциональные удобства, которые добавляют поддержку tsconfig.json, разрешение псевдонимов путей и полные трансформации TypeScript без флагов. Используйте их только если вашей настройке нужны эти возможности.
При использовании встроенного удаления типов Node выполняет ваши .ts файлы напрямую, поэтому номера строк в трассировках стека соответствуют вашему исходному коду. Для скомпилированного кода включите sourceMap в tsconfig.json, и Node автоматически будет использовать .js.map файлы для отображения исходных местоположений TypeScript в ошибках и сеансах отладки.
Complete picture for complete understanding
Capture every clue your frontend is leaving so you can instantly get to the root cause of any issue with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Check our GitHub repo and join the thousands of developers in our community.