Модули
Глобальный модуль
По умолчанию, когда вы начинаете писать код в новом файле TypeScript, он находится в глобальном пространстве имен. Например, следующий код в foo.ts:
const foo = 123;Если вы создадите новый файл bar.ts в том же проекте, система типов TypeScript позволит вам использовать переменную foo, как если бы она была доступна глобально:
const bar = foo; // allowedИспользование пространства глобальных переменных опасно, поскольку оно конфликтует с переменными в файле. Мы рекомендуем использовать файловый модуль, указанный ниже.
Файловый модуль
Он также называется внешним модулем. Если вы включите import или export на корневом уровне вашего файла TypeScript, он создаст локальную область в этом файле. Поэтому нам нужно изменить вышеприведенный foo.ts к следующему виду (обратите внимание на использование export):
export const foo = 123;В глобальном пространстве имен у нас больше нет переменной foo, что можно доказать, создав новый файл bar.ts:
const bar = foo; // ERROR: "cannot find name 'foo'"Если вы хотите использовать переменные из foo.ts в bar.ts, вы должны явно импортировать его и обновить bar.ts следующим образом:
import { foo } from './foo';
const bar = foo; // allowИспользование 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), должна находиться находиться в родительском каталоге.
Или вы можете подумать о других сценариях импорта относительных путей. 😀
Динамический поиск
Когда путь импорта не является относительным путем, в силу вступает поиск модуля nodejs . Я приведу простой пример ниже:
Когда вы используете
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
Вы можете выбрать, чтобы загружалась только информация о типе и не возникала зависимость во время выполнения. Прежде чем продолжить, вы можете вспомнить раздел пространство деклараций в этой книге.
Если вы не используете импортированное имя в пространстве объявления переменных, то импорт полностью удаляется из сгенерированного JavaScript. Это лучше всего объяснить на примерах. Как только вы поймете это, мы представим вам варианты использования.
Пример 1
сгенерирует JavaScript:
Это правильно, пустой файл, который не используется.
Пример 2
сгенерирует JavaScript:
Это потому, что foo (или любой другой атрибут, такой как foo.bas) не используется в качестве переменной.
Пример 3
сгенерирует JavaScript (при условии, что module: commonjs):
Это потому, что foo используется как переменная.
Пример использования: ленивая загрузка
Вывод типа должен быть сделан заранее. Это означает, что если вы хотите использовать какой-либо тип из файла foo в файле , вам нужно будет сделать:
Однако в некоторых сценариях вы хотите загружать модуль foo только тогда, когда это необходимо, и вам нужно использовать имя импортированного модуля только в аннотации типа, а не в переменной. Они будут удалены при компиляции в JavaScript. Затем вы можете вручную импортировать нужные вам модули.
Не менее простой модуль amd (с использованием requirejs):
Они обычно используются в следующих сценариях:
В веб-приложении, когда вы загружаете JavaScript по определенному маршруту;
В приложениях
nodejs, когда вы хотите загрузить только определенные модули, чтобы ускорить запуск.
Пример использования: нарушение круговых зависимостей
Как и в случае использования отложенной загрузки, некоторые загрузчики модулей (commonjs / node и amd / requirejs) плохо обрабатывают циклические зависимости. В этом случае, с одной стороны, мы используем ленивый код загрузки, а с другой - полезно предварительно загрузить модуль.
Пример использования: обязательно импортируйте
Иногда вы хотите загрузить файл только для побочного эффекта (например, модуль может зарегистрироваться в некоторой библиотеке, такой как дополнения CodeMirror и т. д.). Однако, если вы просто выполняете import/require , скомпилированный JavaScript не будет содержать зависимости от модуля, и ваш загрузчик модулей (например, веб-пакет) может полностью игнорировать импорт. В таких случаях вы можете использовать переменную sureImport, чтобы гарантировать, что скомпилированный JavaScript принимает зависимость от модуля, например:
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?