Как запускать TypeScript нативно в Node.js

Node.js 23.6.0 знаменует поворотный момент для разработчиков TypeScript: теперь вы можете выполнять .ts
файлы напрямую без инструментов транспиляции, таких как ts-node или tsc. Эта нативная поддержка TypeScript упрощает рабочие процессы разработки, устраняя этапы сборки при сохранении типобезопасности через вашу IDE.
Это руководство охватывает все, что вам нужно знать для запуска TypeScript нативно в Node.js, от базовой настройки до производственных соображений. Вы узнаете, как работает удаление типов, какие возможности TypeScript поддерживаются, и как настроить ваши проекты для оптимальной совместимости.
Ключевые моменты
- Node.js 23.6.0 выполняет файлы TypeScript напрямую без транспиляции
- Удаление типов убирает аннотации, сохраняя структуру кода
- Большинство распространенных возможностей TypeScript работают, но enum и namespace требуют обходных решений
- Операторы импорта должны включать расширение
.ts
- Нативное выполнение обеспечивает в 2-3 раза более быстрое время запуска по сравнению с традиционными инструментами
Быстрый старт: Запуск TypeScript в Node.js 23.6.0
Начнем с простого файла TypeScript для демонстрации нативного выполнения:
// greeting.ts
function greet(name: string): string {
return `Hello, ${name}!`
}
console.log(greet("TypeScript"))
С Node.js 23.6.0 или новее запустите это напрямую:
node greeting.ts
Вот и все — никаких этапов компиляции не требуется. Node.js удаляет аннотации типов и выполняет оставшийся JavaScript.
Чтобы проверить версию Node.js:
node --version # Должно быть v23.6.0 или выше
При первом запуске вы увидите экспериментальное предупреждение:
ExperimentalWarning: Type Stripping is an experimental feature and might change at any time
Чтобы подавить это предупреждение в разработке:
node --disable-warning=ExperimentalWarning greeting.ts
Или установите это постоянно:
export NODE_OPTIONS="--disable-warning=ExperimentalWarning"
Понимание удаления типов в Node.js
Удаление типов принципиально отличается от традиционной транспиляции TypeScript. Вместо преобразования TypeScript в JavaScript, Node.js просто удаляет аннотации типов, сохраняя исходную структуру кода.
Вот что происходит во время удаления типов:
// Исходный TypeScript
function calculate(a: number, b: number): number {
return a + b
}
// После удаления типов (что выполняет Node.js)
function calculate(a , b ) {
return a + b
}
Обратите внимание на сохранение пробелов — это поддерживает точные номера строк для отладки без необходимости в source maps.
Преимущества производительности
Нативное выполнение TypeScript предлагает значительные улучшения производительности:
- Отсутствие накладных расходов транспиляции: Прямое выполнение без промежуточных этапов
- Более быстрое время запуска: ~45мс против 120мс с ts-node
- Сниженное использование памяти: Транспилятор не загружается в память
- Упрощенная отладка: Сохраняются исходные номера строк
Эволюция поддержки TypeScript в Node.js
Понимание прогресса поможет вам выбрать правильный подход:
v22.6.0: Начальное удаление типов
node --experimental-strip-types app.ts
Только базовое удаление типов — без поддержки специфичного для TypeScript синтаксиса.
v22.7.0: Трансформация типов
node --experimental-transform-types app.ts
Добавлена поддержка enum и namespace через трансформацию.
v23.6.0: Удаление типов по умолчанию
node app.ts # Удаление типов включено по умолчанию
Флаг не нужен для базового выполнения TypeScript.
Поддерживаемые возможности TypeScript и ограничения
Что работает
Нативный TypeScript в Node.js поддерживает большинство повседневных возможностей TypeScript:
// ✅ Аннотации типов
let count: number = 0
// ✅ Интерфейсы
interface User {
id: number
name: string
}
// ✅ Псевдонимы типов
type Status = 'active' | 'inactive'
// ✅ Дженерики
function identity<T>(value: T): T {
return value
}
// ✅ Импорт типов
import type { Config } from './types.ts'
Что не работает
Некоторые специфичные для TypeScript возможности требуют обходных решений:
Возможность | Поддерживается | Обходное решение |
---|---|---|
Enum | ❌ | Используйте union типы или const объекты |
Namespace | ❌ | Используйте ES модули |
Свойства параметров | ❌ | Явные объявления свойств |
JSX/TSX | ❌ | Используйте традиционную транспиляцию |
Декораторы | ❌ | Ждите поддержки V8 |
Примеры обходных решений:
// ❌ Enum (не поддерживается)
enum Status {
Active,
Inactive
}
// ✅ Альтернатива с union типом
type Status = 'active' | 'inactive'
// ✅ Альтернатива с const объектом
const Status = {
Active: 'active',
Inactive: 'inactive'
} as const
Discover how at OpenReplay.com.
Расширения файлов и модульные системы
Node.js использует расширения файлов для определения обработки модулей:
.ts
- Следует полю"type"
в package.json (ESM или CommonJS).mts
- Всегда обрабатывается как ESM.cts
- Всегда обрабатывается как CommonJS
Важно: Локальные импорты должны включать расширение .ts
:
// ❌ Традиционный TypeScript
import { utils } from './utils'
// ✅ Нативный TypeScript Node.js
import { utils } from './utils.ts'
Настройка tsconfig.json для нативного TypeScript
Хотя Node.js не читает tsconfig.json во время выполнения, правильная конфигурация обеспечивает поддержку IDE и проверку типов:
{
"compilerOptions": {
"target": "esnext",
"module": "nodenext",
"moduleResolution": "nodenext",
"allowImportingTsExtensions": true,
"rewriteRelativeImportExtensions": false,
"verbatimModuleSyntax": true,
"strict": true,
"noEmit": true
}
}
Объяснение ключевых настроек:
allowImportingTsExtensions
: Разрешает.ts
в путях импортаrewriteRelativeImportExtensions
: Установите в false для сохранения расширений.ts
verbatimModuleSyntax
: Принуждает к явным импортам типовnoEmit
: Предотвращает случайную генерацию JavaScript
Запускайте проверку типов отдельно:
tsc --noEmit
Руководство по миграции с традиционных инструментов TypeScript
Миграция с ts-node
- Удалите зависимость ts-node:
npm uninstall ts-node
- Обновите скрипты в package.json:
// Раньше
"scripts": {
"dev": "ts-node src/index.ts"
}
// Теперь
"scripts": {
"dev": "node src/index.ts"
}
- Обработайте неподдерживаемые возможности (конвертируйте enum в union)
Миграция с компиляции tsc
- Удалите этапы сборки:
// Удалите эти скрипты
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
}
// Используйте это вместо
"scripts": {
"start": "node src/index.ts"
}
- Обновите CI/CD пайплайны, чтобы пропустить компиляцию
Сравнение производительности
Нативное выполнение TypeScript показывает значительные улучшения:
Метрика | Нативный TypeScript | ts-node | tsc + node |
---|---|---|---|
Время запуска | ~45мс | ~120мс | ~200мс |
Использование памяти | Базовое | +30МБ | +10МБ |
Этап сборки | Отсутствует | Отсутствует | Требуется |
Распространенные подводные камни и решения
Ошибки путей импорта
// Ошибка: Cannot find module './utils'
import { helper } from './utils'
// Решение: Включите расширение .ts
import { helper } from './utils.ts'
Неподдерживаемый синтаксис
// Ошибка: Enums are not supported
enum Color { Red, Blue }
// Решение: Используйте const объект
const Color = { Red: 0, Blue: 1 } as const
Путаница с проверкой типов
Помните: Node.js не выполняет проверку типов. Всегда запускайте tsc --noEmit
для валидации типов.
Соображения для продакшена
Когда использовать нативный TypeScript
- Среды разработки
- Прототипы и эксперименты
- Небольшие скрипты и утилиты
- Команды, готовые к экспериментальным возможностям
Когда избегать
- Продакшен приложения (пока не стабилизируется)
- Проекты, требующие полных возможностей TypeScript
- Команды, нуждающиеся в стабильном инструментарии
- Сложные пайплайны сборки
Корректировки Docker
# Раньше
FROM node:23-alpine
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
CMD ["node", "dist/index.js"]
# Теперь
FROM node:23-alpine
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["node", "src/index.ts"]
Заключение
Нативная поддержка TypeScript в Node.js 23.6.0 представляет значительное упрощение рабочих процессов разработки. Устраняя этапы транспиляции, вы можете сосредоточиться на написании кода, а не на настройке инструментов сборки. Хотя ограничения существуют — особенно касательно специфичного для TypeScript синтаксиса — преимущества для большинства сценариев разработки убедительны.
Начните с попытки использования нативного TypeScript в вашей среде разработки, постепенно мигрируйте существующие проекты и готовьтесь к будущему, где TypeScript работает везде, где работает JavaScript. По мере стабилизации этой возможности ожидайте более широкого принятия и расширенных возможностей в предстоящих релизах Node.js.
Часто задаваемые вопросы
Хотя технически это возможно, для продакшена это пока не рекомендуется. Функция все еще экспериментальная и может измениться. Используйте ее для сред разработки, прототипов и некритичных приложений. Для продакшена продолжайте использовать традиционную транспиляцию до стабилизации функции.
Да, вы должны сохранить TypeScript как зависимость разработки для проверки типов. Node.js только удаляет типы без их валидации. Запускайте tsc --noEmit отдельно для обнаружения ошибок типов во время разработки или в вашем CI пайплайне.
Нативный TypeScript требует явных расширений .ts в путях импорта, в отличие от традиционного инструментария TypeScript. Обновите все локальные импорты с './module' на './module.ts'. Импорты внешних пакетов не нуждаются в расширениях.
Замените enum на union типы для простых случаев или const объекты с утверждением as const для числовых enum. Для строковых enum union типы работают идеально. Этот подход фактически лучше поддается tree-shaking и лучше соответствует современным практикам TypeScript.
Команда Node.js фокусируется на удалении типов, а не на полной транспиляции из соображений производительности. Возможности, требующие runtime трансформации, такие как enum и декораторы, могут получить поддержку, когда V8 реализует их нативно, но цель — быстрая, минимальная обработка, а не полная совместимость с 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.