Typescript Глубокое Погружение
  • Typescript Глубокое Погружение
  • Typescript проект
    • Контекст компиляции
    • Пространство декларации
    • Модули
    • Пространства имен
    • Динамический импорт выражений
  • Typescript Система типов
    • Обзор
    • Миграция с JavaScript
    • @types
    • Декларация окружения
    • Интерфейсы
    • Перечисления
    • lib.d.ts
    • Функции
    • Подлежащий выкупу
    • Тип утверждения
    • Freshness
    • Тип защиты
    • Литеральный тип
    • readonly
    • Дженерики
    • Тип вывода
    • Тип совместимости
Powered by GitBook
On this page
  • Глобальный модуль
  • Файловый модуль
  • Детали файлового модуля
  • Пояснения: commonjs, amd, es modules, others
  • Синтаксис модуля ES
  • Импорт / экспорт по умолчанию
  • Модульные пути
  • Что такое `place`
  • Переопределить тип динамического поиска
  • import/require только для типов
  • Пример использования: ленивая загрузка
  • Пример использования: нарушение круговых зависимостей
  • Пример использования: обязательно импортируйте
  • global.d.ts

Was this helpful?

  1. Typescript проект

Модули

Глобальный модуль

По умолчанию, когда вы начинаете писать код в новом файле 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.

Импортируйте, экспортируйте и записывайте модули, используя параметр module: commonjs и используя синтаксис модуля ES.

Синтаксис модуля ES

  • Используйте ключевое слово export для экспорта переменной (или типа):

// foo.ts
export const someVar = 123;
export type someType = {
  foo: string;
};
  • Экспорт переменной или типа в отдельном операторе export:

// foo.ts
const someVar = 123;
type someType = {
  type: string;
};

export { someVar, someType };
  • Вы также можете переименовать переменные для экспорта:

// foo.ts
const someVar = 123;
export { someVar as aDifferentName };
  • Используйте ключевое слово import для импорта переменной или типа:

// bar.ts
import { someVar, someType } from './foo';
  • Переименуйте импортированные переменные или типы:

// bar.ts
import { someVar as aDifferentName } from './foo';
  • Помимо указания выходного значения для загрузки, вы также можете использовать глобальную загрузку, то есть указать объект со звездочкой (*), и все выходные значения будут загружены в этот объект:

// bar.ts
import * as foo from './foo';
// Вы можете использовать `foo.someVar` и` foo.someType` и
// любые другие переменные или типы, экспортированные из `foo`
  • Импортируйте файл только для побочного эффекта с помощью одного оператора import:

import 'core-js'; // стандартная библиотека polyfill
  • Общий экспорт после импорта из других модулей:

export * from './foo';
  • Реэкспорт только конкретных из другого модуля

export { someVar } from './foo';
  • Реэкспорт только конкретных из другого модуля с переименованием

export { someVar as aDifferentName } from './foo';

Импорт / экспорт по умолчанию

Я не люблю использовать экспорт по умолчанию, тем не менее вот синтаксис экспорта по умолчанию:

  • Использование export default :

    • Перед переменной (не нужно использовать let / const / var);

    • Перед функцией;

    • Перед классом.

// some var
export default someVar = 123;

// some function
export default function someFunction() {}

// some class
export default class SomeClass {}
  • При импорте используется import someName from 'someModule (вы можете указать любое имя при необходимости):

import someLocalNameForThisFile from './foo';

Модульные пути

Если вам нужно использовать параметр moduleResolution: node, вам нужно добавить его в файл конфигурации. Если вы используете опцию module: commonjs, то по умолчанию будет включен moduleResolution: node.

Есть два разных вида модулей:

  • Относительный путь к модулю (путь начинается с .(точка), например: ./someFile или ../../someFolder/someFile и т. д.);

  • Другие модули динамического поиска (например: core-js, typestyle, react или даже react/core ​​и т. д.).

Основное отличие состоит в том, как модуль расположен в файловой системе.

Я буду использовать концептуальный термин place - я объясню его, когда упомяну шаблон поиска.

Относительный путь модуля

Это просто, просто следуйте по относительному пути:

  • Если файл 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' для решения проблемы поиска пути к модулю:

// global.d.ts
declare module 'foo' {
  // some variable declarations
  export var bar: number;
}

а потом:

// anyOtherTsFileInYourProject.ts
import * as foo from 'foo';
// TypeScript предполагает (без поиска), что
// foo это { bar: number }

import/require только для типов

Следующий синтаксис импорта:

import foo = require('foo');

На самом деле он делает только две вещи:

  • Импортировать всю информацию о типе модуля foo;

  • Определите зависимости времени выполнения модуля foo

Пример 1

import foo = require('foo');

сгенерирует JavaScript:

Это правильно, пустой файл, который не используется.

Пример 2

import foo = require('foo');
let bar: foo;

сгенерирует JavaScript:

let bar;

Это потому, что foo (или любой другой атрибут, такой как foo.bas) не используется в качестве переменной.

Пример 3

import foo = require('foo');
const bar = foo;

сгенерирует JavaScript (при условии, что module: commonjs):

const foo = require('foo');
const bar = foo;

Это потому, что foo используется как переменная.

Пример использования: ленивая загрузка

Вывод типа должен быть сделан заранее. Это означает, что если вы хотите использовать какой-либо тип из файла foo в файле , вам нужно будет сделать:

import foo = require('foo');
let bar: foo.SomeType;

Однако в некоторых сценариях вы хотите загружать модуль foo только тогда, когда это необходимо, и вам нужно использовать имя импортированного модуля только в аннотации типа, а не в переменной. Они будут удалены при компиляции в JavaScript. Затем вы можете вручную импортировать нужные вам модули.

import foo = require('foo');

export function loadFoo() {
  // Это ленивая загрузка foo, оригинальная загрузка используется только для аннотаций типов
  const _foo: typeof foo = require('foo');
  // Теперь вы можете использовать `_foo` вместо` foo` в качестве переменной
}

Не менее простой модуль amd (с использованием requirejs):

import foo = require('foo');

export function loadFoo() {
  // Это ленивая загрузка foo, оригинальная загрузка используется только для аннотаций типов
  require(['foo'], (_foo: typeof foo) => {
    // Теперь вы можете использовать `_foo` вместо` foo` в качестве переменной
  });
}

Они обычно используются в следующих сценариях:

  • В веб-приложении, когда вы загружаете JavaScript по определенному маршруту;

  • В приложениях nodejs, когда вы хотите загрузить только определенные модули, чтобы ускорить запуск.

Пример использования: нарушение круговых зависимостей

Как и в случае использования отложенной загрузки, некоторые загрузчики модулей (commonjs / node и amd / requirejs) плохо обрабатывают циклические зависимости. В этом случае, с одной стороны, мы используем ленивый код загрузки, а с другой - полезно предварительно загрузить модуль.

Пример использования: обязательно импортируйте

import foo = require('./foo');
import bar = require('./bar');
import bas = require('./bas');

const ensureImport: any = foo || bar || bas;

global.d.ts

Выше, когда мы обсуждали файловые модули, мы сравнивали глобальные переменные с файловыми модулями, и мы рекомендуем использовать файловые модули, а не загрязнять глобальное пространство имен.

Однако, если в вашей команде есть начинающие TypeScript разработчики, вы можете предоставить им файл global.d.ts для размещения некоторых интерфейсов или типов в глобальном пространстве имен. Эти определенные интерфейсы и типы могут использоваться во всех ваших TypeScript файлах.

Для любого кода, который необходимо скомпилировать в JavaScript, мы настоятельно рекомендуем поместить его в файловый модуль.

  • global.d.ts - отличный способ расширить lib.d.ts, если вам нужно.

  • Когда вы переходите с JS на TS, определение модуля объявлений 'some-library-you-dont-care-to-get-defs-for' поможет вам быстро начать работу.

PreviousПространство декларацииNextПространства имен

Last updated 5 years ago

Was this helpful?

Или вы можете подумать о других сценариях импорта относительных путей.

Когда путь импорта не является относительным путем, в силу вступает . Я приведу простой пример ниже:

Вы можете выбрать, чтобы загружалась только информация о типе и не возникала зависимость во время выполнения. Прежде чем продолжить, вы можете вспомнить раздел в этой книге.

Если вы не используете импортированное имя в , то импорт полностью удаляется из сгенерированного JavaScript. Это лучше всего объяснить на примерах. Как только вы поймете это, мы представим вам варианты использования.

Иногда вы хотите загрузить файл только для побочного эффекта (например, модуль может зарегистрироваться в некоторой библиотеке, такой как и т. д.). Однако, если вы просто выполняете import/require , скомпилированный JavaScript не будет содержать зависимости от модуля, и ваш загрузчик модулей (например, веб-пакет) может полностью игнорировать импорт. В таких случаях вы можете использовать переменную sureImport, чтобы гарантировать, что скомпилированный JavaScript принимает зависимость от модуля, например:

😀
поиск модуля nodejs
пространство деклараций
пространстве объявления переменных
дополнения CodeMirror