Модули, tsconfig, сборка и интеграция с JavaScript
На предыдущих этапах курса мы учились описывать типы (базовые типы, type и interface), строить API-контракты и применять дженерики и utility types. Но в реальном проекте типизация не живёт в вакууме: код нужно
организовать по файлам и модулям
настроить правила компиляции в tsconfig.json
собрать проект в JavaScript
часто смешать TypeScript и JavaScript в одной кодовой базеЭта статья связывает типизацию с инфраструктурой: как TypeScript превращается в рабочий JavaScript, как проект «видит» модули и как безопасно внедрять TS в существующий JS.
!Схема показывает, что TypeScript проверяет типы и компилирует исходники в JS, а также может генерировать типы и sourcemap
Что такое модуль в TypeScript
Модуль — это файл, который имеет собственную область видимости и может экспортировать значения (функции, классы, константы, типы), а также импортировать их из других файлов.
В TypeScript есть важное разделение:
значения существуют в рантайме (например, функция, класс, объект)
типы существуют только на этапе компиляции (например, type, interface)Это влияет на импорт/экспорт.
export и import: базовый синтаксис
Экспорт значений
Импорт:
Экспорт по умолчанию
Импорт:
Практическое замечание: default export удобен для одного главного объекта из файла, но именованные экспорты часто проще для рефакторинга и автодополнения.
Реэкспорт
Так можно сделать «публичный вход» пакета.
Импорт и экспорт типов
Поскольку типы стираются при компиляции, TypeScript предлагает явный синтаксис импорта типов.
import type полезен тем, что:
подчёркивает, что это только тип
помогает инструментам сборки точнее убирать лишние импортыTypeScript также умеет export type { User } для реэкспорта именно типов.
ES Modules и CommonJS: две системы модулей
В JavaScript исторически есть две основные системы модулей.
ES Modules (ESM): import / export
CommonJS (CJS): require() / module.exportsTypeScript умеет компилировать код под обе системы. Выбор влияет на настройки tsconfig.json и на запуск в Node.js.
Быстрая таблица различий
| Тема | ESM | CJS |
|---|---|---|
| Синтаксис | import/export | require/module.exports |
| Node.js | современный стандарт, требует корректных настроек | классический вариант для Node.js |
| Совместимость | иногда требует явных расширений и настроек | часто проще с legacy-пакетами |
Официальные источники:
TypeScript Handbook: Modules
Node.js Documentation: ECMAScript modulestsconfig.json: что это и зачем
tsconfig.json — это файл конфигурации TypeScript-проекта. Он определяет:
какие файлы входят в проект
какие правила типизации включены
во что и как компилировать (target, module)
куда класть результат (outDir)Минимальный пример:
include, exclude и files
include — какие пути включить (например, src)
exclude — что исключить (часто исключают dist, node_modules)
files — точечный список файлов (используют реже)Пример:
Ключевые compilerOptions, которые встречаются в большинстве проектов
target: в какой JavaScript компилировать
target задаёт версию JavaScript, в которую компилируется TypeScript.
более высокий target сохраняет больше современных возможностей (часто меньше и быстрее код)
более низкий target может быть нужен для старых средПримеры значений: ES2017, ES2020, ES2022.
module: какую систему модулей генерировать
module определяет, как будут выглядеть импорты/экспорты в итоговом JavaScript.
Частые варианты:
"module": "CommonJS" для CJS
"module": "ES2020" или "module": "NodeNext" для ESM в Node.jsЕсли вы делаете библиотеку, выбор module часто согласуют с тем, как её будут подключать.
strict: базовый переключатель строгости
strict: true включает набор строгих проверок (в том числе strictNullChecks, о котором мы говорили в теме базовых типов).
Практически для обучения и для большинства продакшн-проектов лучше считать strict: true нормой.
rootDir и outDir: структура входа и выхода
rootDir — откуда компилятор «считает» корень исходников
outDir — куда складывать скомпилированный JSПример:
Типичная структура:
src — исходники
dist — результат сборкиlib: какие встроенные API доступны
lib определяет, какие стандартные библиотеки доступны типам (например, DOM-API или современные методы массивов).
Пример для Node.js (без DOM):
Пример для браузера:
moduleResolution: как искать модули
Эта опция отвечает за то, как TypeScript ищет модули по import.
Для современных Node.js ESM-проектов часто выбирают NodeNext.
baseUrl и paths: удобные алиасы импортов
Вместо длинных относительных путей:
можно настроить алиасы:
и импортировать так:
Важно: paths влияет на TypeScript (типизацию и компиляцию), но не всегда автоматически на рантайм. Если вы используете алиасы, убедитесь, что ваша система сборки/запуска тоже их понимает (конкретное решение зависит от инструмента).
Официальная документация:
TypeScript Handbook: tsconfig.json
TypeScript Compiler OptionsСборка: как компилировать TypeScript в JavaScript
tsc как основной компилятор
TypeScript устанавливается как пакет typescript, а команда компиляции обычно выглядит так:
tsc:
читает tsconfig.json
проверяет типы
генерирует JavaScript в outDir (если он задан)Частые опции сборки
sourceMap: true — генерирует .map файлы для отладки (чтобы в девтулз видеть исходный TS)
declaration: true — генерирует .d.ts файлы (полезно для библиотек)
noEmit: true — не генерировать JS, только проверять типы (часто используют в CI)Пример конфигурации для библиотеки:
Инкрементальная сборка
Для ускорения сборки больших проектов можно включить incremental: true. Тогда TypeScript будет хранить информацию о прошлой компиляции и пересобирать только изменённое.
Интеграция с JavaScript: постепенный переход и смешанные проекты
TypeScript задуман как постепенно внедряемый. Это означает, что вы можете держать в проекте и .ts, и .js.
allowJs: включить JavaScript-файлы в проект
Если у вас уже есть JavaScript-код, можно разрешить его обработку компилятором:
allowJs: true — TypeScript будет включать .js файлы
checkJs: false — по умолчанию он не будет строго проверять типы в .jscheckJs: проверка типов прямо в JavaScript
Если включить checkJs: true, TypeScript начнёт проверять JavaScript-файлы. Это полезно, если вы хотите улучшать качество кода до миграции на .ts.
JSDoc-типы в JavaScript
Даже в .js можно добавлять типы через JSDoc.
TypeScript сможет использовать эти типы для подсказок и проверок (при checkJs: true).
Официальная документация:
TypeScript Handbook: Type Checking JavaScript Files
TypeScript Handbook: JSDoc ReferenceКак TypeScript «понимает» типы из JavaScript-модулей
В смешанном проекте у вас есть несколько вариантов:
мигрировать файл на .ts и добавить нормальные типы
добавить JSDoc
создать рядом .d.ts файл с объявлениями типовПример: есть src/legacy.js:
Можно добавить декларацию src/legacy.d.ts:
И тогда TypeScript-код, импортирующий makeUser, получит корректные типы.
Совместимость импортов: esModuleInterop и default import
Если вы работаете с CommonJS-библиотеками (особенно в Node.js), часто встречается ситуация, когда хочется писать:
Для этого во многих проектах включают:
Смысл: сделать импорт CJS-модулей более удобным в стиле ESM. Эта настройка часто упрощает жизнь, но её лучше включать осознанно и консистентно в проекте.
Официальная документация:
TypeScript Compiler Option: esModuleInteropПрактический шаблон конфигурации для небольшого Node.js-проекта
Ниже пример, который часто подходит для учебных и небольших сервисов.
Структура
src/index.ts
dist/index.js
tsconfig.jsontsconfig.json (вариант под современные Node.js ESM)
Коротко про skipLibCheck: он отключает проверку типов в декларациях зависимостей (.d.ts внутри node_modules). Это часто ускоряет сборку и снижает шум, но не лечит реальные проблемы в вашем коде.
Типичные ошибки и как их диагностировать
Собралось, но не запускается в Node.js
- Проверьте согласованность
module и способа запуска (ESM/CJS).
- Посмотрите документацию Node.js по ESM и настройку проекта.
TypeScript видит алиасы, но рантайм не видит
-
paths не всегда работает «сам по себе» при запуске. Нужна поддержка со стороны сборщика/раннера.
Слишком много ошибок после включения strict
- Это нормально при миграции. Двигайтесь постепенно: начните с критичных модулей, используйте
unknown вместо
any, добавляйте проверки и уточнения типов.
Итог
Теперь у вас есть инфраструктурная база, которая связывает все предыдущие темы курса в рабочий проект:
вы понимаете, как устроены модули, и как разделяются импорты значений и импорты типов
вы умеете настраивать tsconfig.json: target, module, strict, outDir, rootDir, baseUrl/paths
вы знаете, как TypeScript компилируется через tsc, и какие опции важны для сборки (sourceMap, declaration, noEmit)
вы понимаете стратегии интеграции с JavaScript: allowJs, checkJs, JSDoc и .d.tsЭти навыки нужны, чтобы типы работали не только в примерах, но и в настоящей кодовой базе: с файлами, импортами, сборкой, публикацией и постепенной миграцией.