Модули
Глобальный модуль
По умолчанию, когда вы начинаете писать код в новом файле TypeScript, он находится в глобальном пространстве имен. Например, следующий код в foo.ts
:
Если вы создадите новый файл bar.ts
в том же проекте, система типов TypeScript позволит вам использовать переменную foo
, как если бы она была доступна глобально:
Использование пространства глобальных переменных опасно, поскольку оно конфликтует с переменными в файле. Мы рекомендуем использовать файловый модуль, указанный ниже.
Файловый модуль
Он также называется внешним модулем. Если вы включите import
или export
на корневом уровне вашего файла TypeScript, он создаст локальную область в этом файле. Поэтому нам нужно изменить вышеприведенный foo.ts
к следующему виду (обратите внимание на использование export
):
В глобальном пространстве имен у нас больше нет переменной foo
, что можно доказать, создав новый файл bar.ts
:
Если вы хотите использовать переменные из foo.ts
в bar.ts
, вы должны явно импортировать его и обновить bar.ts
следующим образом:
Использование import
в файле bar.ts
не только позволяет использовать содержимое, импортированное из других файлов, но и помечает этот файл bar.ts
как модуль, а объявления, определенные в файле, не будут загрязнять глобальное пространство имен.
Детали файлового модуля
Файловый модуль обладает мощными возможностями и удобством использования. Здесь мы обсудим его возможности и некоторые применения.
Пояснения: commonjs, amd, es modules, others
Во-первых, нам нужно прояснить несоответствия этих модульных систем. Я предоставлю вам мой текущий совет и некоторые проблемы.
Вы можете скомпилировать TypeScript в разные типы модулей JavaScript, основываясь на разных параметрах module
. Вот некоторые вещи, которые вы можете игнорировать:
AMD: не используйте его, он работает только в браузере;
SystemJS: Это был хороший эксперимент, и его заменили модули ES;
Модуль ES: не готов.
Хорошей идеей является использование параметра module: commonjs
вместо указанных выше.
Как писать модули TypeScript также сбивает с толку. Сегодня мы должны делать так:
Отказаться от использования синтаксиса
import / require
, т.е.import foo = require ('foo')
Вместо этого используйте синтаксис модуля ES
Круто, давайте посмотрим на синтаксис модуля ES.
Синтаксис модуля ES
Используйте ключевое слово
export
для экспорта переменной (или типа):
Экспорт переменной или типа в отдельном операторе
export
:
Вы также можете переименовать переменные для экспорта:
Используйте ключевое слово
import
для импорта переменной или типа:
Переименуйте импортированные переменные или типы:
Помимо указания выходного значения для загрузки, вы также можете использовать глобальную загрузку, то есть указать объект со звездочкой (*), и все выходные значения будут загружены в этот объект:
Импортируйте файл только для побочного эффекта с помощью одного оператора import:
Общий экспорт после импорта из других модулей:
Реэкспорт только конкретных из другого модуля
Реэкспорт только конкретных из другого модуля с переименованием
Импорт / экспорт по умолчанию
Я не люблю использовать экспорт по умолчанию, тем не менее вот синтаксис экспорта по умолчанию:
Использование
export default
:Перед переменной (не нужно использовать
let
/const
/var
);Перед функцией;
Перед классом.
При импорте используется
import someName from 'someModule
(вы можете указать любое имя при необходимости):
Модульные пути
Есть два разных вида модулей:
Относительный путь к модулю (путь начинается с
.
(точка), например:./someFile
или../../someFolder/someFile
и т. д.);Другие модули динамического поиска (например:
core-js
,typestyle
,react
или дажеreact/core
и т. д.).
Основное отличие состоит в том, как модуль расположен в файловой системе.
Относительный путь модуля
Это просто, просто следуйте по относительному пути:
Если файл
bar.ts
содержитimport * as foo from './foo'
, то при таком построении файл foo, должен находиться в той же папке;Если файл
bar.ts
содержитimport * as foo from '../foo'
, то при таком построении файл foo, должен находиться в родительском каталоге;Если файл
bar.ts
содержитimport * as foo from '../someFolder/foo'
, папка, в которой находится файлfoo
(someFolder), должна находиться находиться в родительском каталоге.
Динамический поиск
Когда вы используете
import * as foo from 'foo'
, модули ищутся в следующем порядке:./node_modules/foo
../node_modules/foo
../../node_modules/foo
И так до корня системы
Когда вы используете
import * as foo from 'thing/foo'
, содержимое будет искать в следующем порядке:./node_modules/something/foo
../node_modules/something/foo
../../node_modules/something/foo
И так до корня системы
Что такое `place`
Когда я упоминаю проверяемое place
, я хочу сказать, что в этом place
TypeScript проверит следующее (например, местоположение foo):
Если это
place
представляет файл, такой как:foo.ts
, ура!В противном случае, если это
place
является папкой и существует файлfoo/index.ts
, ура!В противном случае, если это
place
является папкой и существует файлfoo/package.json
, и в нем естьtypes
указывающий на типы, ура!В противном случае, если это
place
является папкой и в ней существует файлpackage.json
с указаниемmain
параметра в этом файле, ура!
Под файлом я имею в виду .ts
/ .d.ts
и .js
.
Вот и все, теперь вы эксперт по поиску модулей (это немалый успех).
Переопределить тип динамического поиска
В вашем проекте вы можете объявить глобальный модуль, declate module 'somePath'
для решения проблемы поиска пути к модулю:
а потом:
import/require
только для типов
import/require
только для типовСледующий синтаксис импорта:
На самом деле он делает только две вещи:
Импортировать всю информацию о типе модуля
foo
;Определите зависимости времени выполнения модуля
foo
Пример 1
сгенерирует JavaScript:
Это правильно, пустой файл, который не используется.
Пример 2
сгенерирует JavaScript:
Это потому, что foo
(или любой другой атрибут, такой как foo.bas
) не используется в качестве переменной.
Пример 3
сгенерирует JavaScript (при условии, что module: commonjs
):
Это потому, что foo
используется как переменная.
Пример использования: ленивая загрузка
Вывод типа должен быть сделан заранее. Это означает, что если вы хотите использовать какой-либо тип из файла foo
в файле , вам нужно будет сделать:
Однако в некоторых сценариях вы хотите загружать модуль foo
только тогда, когда это необходимо, и вам нужно использовать имя импортированного модуля только в аннотации типа, а не в переменной. Они будут удалены при компиляции в JavaScript. Затем вы можете вручную импортировать нужные вам модули.
Не менее простой модуль amd
(с использованием requirejs):
Они обычно используются в следующих сценариях:
В веб-приложении, когда вы загружаете JavaScript по определенному маршруту;
В приложениях
nodejs
, когда вы хотите загрузить только определенные модули, чтобы ускорить запуск.
Пример использования: нарушение круговых зависимостей
Как и в случае использования отложенной загрузки, некоторые загрузчики модулей (commonjs / node
и amd / requirejs
) плохо обрабатывают циклические зависимости. В этом случае, с одной стороны, мы используем ленивый код загрузки, а с другой - полезно предварительно загрузить модуль.
Пример использования: обязательно импортируйте
global.d.ts
Выше, когда мы обсуждали файловые модули, мы сравнивали глобальные переменные с файловыми модулями, и мы рекомендуем использовать файловые модули, а не загрязнять глобальное пространство имен.
Однако, если в вашей команде есть начинающие TypeScript разработчики, вы можете предоставить им файл global.d.ts
для размещения некоторых интерфейсов или типов в глобальном пространстве имен. Эти определенные интерфейсы и типы могут использоваться во всех ваших TypeScript файлах.
global.d.ts
- отличный способ расширитьlib.d.ts
, если вам нужно.Когда вы переходите с JS на TS, определение модуля объявлений
'some-library-you-dont-care-to-get-defs-for'
поможет вам быстро начать работу.
Last updated
Was this helpful?