Модули
#
Определение модуляВ TS
, как и в ECMAScript2015
, любой файл, содержащий import
или export
верхнего уровня (глобальный), считается модулем.
Файл, не содержащий указанных ключевых слов, является глобальным скриптом.
Модули выполняются в собственной области видимости, а не в глобальной. Это означает, что переменные, функции, классы и т.д., объявленные в модуле, недоступны за пределами модуля до тех пор, пока они в явном виде не будут из него экспортированы. Кроме того, перед использованием экспортированных сущностей, их следует импортировать в соответствующий файл.
#
Не модулиДля начала, давайте разберемся, что TS
считает модулем. Спецификация JS
определяет, что любой файл без export
или await
верхнего уровня является скриптом, а не модулем.
Переменные и типы, объявленные в скрипте, являются глобальными (имеют глобальную область видимости), для объединения нескольких файлов на входе в один на выходе следует использовать либо настроку компилятора outFile
, либо несколько элементов script
в разметке (указанных в правильном порядке).
Если у нас имеется файл, который не содержит import
или export
, но мы хотим, чтобы этот файл считался модулем, просто добавляем в него такую строку:
TS
#
Модули в Существует 3 вещи, на которые следует обращать внимание при работе с модулями в TS
:
- Синтаксис: какой синтаксис я хочу использовать для импорта и экспорта сущностей?
- Разрешение модулей: каковы отношения между названиями модулей (или их путями) и файлами на диске?
- Результат: на что должен быть похож код модуля?
#
СинтаксисОсновной экспорт в файле определяется с помощью export default
:
Затем данная функция импортируется следующим образом:
В дополнению к экспорту по умолчанию, из файла может экспортироваться несколько переменных и функций с помощью export
(без default
):
Указанные сущности импортируются так:
#
Дополнительный синтаксис импортаНазвание импортируемой сущности можно менять с помощью import { old as new }
:
Разные способы импорта можно смешивать:
Все экспортированные объекты при импорте можно поместить в одно пространство имен с помощью * as name
:
Файлы можно импортировать без указания переменных:
В данном случае import
ничего не делает. Тем не менее, весь код из maths.ts
вычисляется (оценивается), что может привести к запуску побочных эффектов, влияющих на другие объекты.
TS
синтаксис модулей#
Специфичный для Типы могут экспортироваться и импортироваться с помощью такого же синтаксиса, что и значения в JS
:
TS
расширяет синтаксис import
с помощью import type
, что позволяет импортировать только типы.
Такой импорт сообщает транспиляторам, вроде Babel
, swc
или esbuild
, какой импорт может быть безопасно удален.
ES-модулей
с поведением CommonJS
#
Синтаксис Синтаксис ES-модулей
в TS
напрямую согласуется с CommonJS
и require
из AMD
. Импорт с помощью ES-модулей
в большинстве случаев представляет собой тоже самое, что require
в указанных окружениях, он позволяет обеспечить полное совпадение TS-файла
с результатом CommonJS
:
CommonJS
#
Синтаксис CommonJS
- это формат, используемый большинством npm-пакетов
. Даже если вы используете только синтаксис ES-модулей
, понимание того, как работает CommonJS
, поможет вам в отладке приложений.
#
ЭкспортИдентификаторы экпортируются посредством установки свойства exports
глобальной переменной module
:
Затем эти файлы импортируются с помощью инструкции require
:
В данном случае импорт можно упростить с помощью деструктуризации:
CommonJS
с ES-модулями
#
Взаимодействие Между CommonJS
и ES-модулями
имеется несовпадение, поскольку ES-модули
поддерживают "дефолтный" экспорт только объектов, но не функций. Для преодоления данного несовпадения в TS
используется флаг компиляции esModuleInterop
.
#
Настройки, связанные с разрешением модулейРазрешение модулей - это процесс определения файла, указанного в качестве ссылки в строке из инструкции import
или require
.
TS
предоставляет две стратегии разрешения модулей: классическую и Node
. Классическая стратегия является стратегией по умолчанию (когда флаг module
имеет значение, отличное от commonjs
) и включается для обеспечения обратной совместимости. Стратегия Node
имитирует работу Node.js
в режиме CommonJS
с дополнительными проверками для .ts
и .d.ts
.
Существует большое количество флагов, связанных с разрешением модулей: moduleResolution
, baseUrl
, paths
, rootDirs
и др.
#
Настройки для результатов разрешения модулейИмеется две настройки, которые влияют на результирующий JS-код
:
- `target` - определяет версию `JS`, в которую компилируется `TS-код`
- `module` - определяет, какой код используется для взаимодействия модулей между собой
То, какую цель (target) использовать, зависит от того, в какой среде будет выполняться код (какие возможности поддерживаются этой средой). Это может включать в себя поддержку старых браузеров, более низкую версию Node.js
или специфические ограничения, накладываемые такими средами выполнения, как, например, Electron
.
Коммуникация между модулями происходит через загрузчик модулей (module loader), определяемый в настройке module
. Во время выполнения загрузчик отвечает за локализацию и установку всех зависимостей модуля перед его выполнением.
Ниже приведено несколько примеров использования синтаксиса ES-модулей
с разными настройками module
:
ES2020
#
CommonJS
#
UMD
#
#
Пространства имен (namespaces)TS
имеет собственный модульный формат, который называется namespaces
. Данный синтаксис имеет множество полезных возможностей по созданию сложных файлов определений и по-прежнему активно используется в DefinitelyTyped
. Несмотря на то, что namespaces
не признаны устаревшими (deprecated), большая часть его возможностей нашла воплощение в ES-модулях
, поэтому настоятельно рекомендуется использовать официальный синтаксис.