Logo
Книга для начинающих
ВходРегистрация
/
Программирование
/
Курс Typescript
/

Система модулей

Typescript: Система модулей

В этом уроке рассмотрим систему модулей TypeScript, которая была создана до стандартизации ESM-модулей.

По умолчанию эта система модулей совместима с Node.js-модулями. Она использует идентичный алгоритм определения импортов и экспортов, при этом синтаксически похожа на ESM. В нем мы используем ключевые слова import/export для импортирования в текущий модуль и экспорта из него, при этом остается валидным использование CommonJS модулей.

Для примера создадим два файла. Из одного будем экспортировать функцию, а в другом импортировать ее:

// @file helloWorld.ts
export default function helloWorld() {
  console.log("Hello, world!");
}

// @file main.ts
import helloWorld from './helloWorld';

В системе модулей TypeScript также поддерживается именованный экспорт/импорт и импорт всего экспортированного через import * as:

// @file helloWorld
export function helloWorld() {}
export function helloWorldAgain() {}

// @file main
import { helloWorld, helloWorldAgain } from './helloWorld';

// @file next
import * as hw from './helloWorld';
hw.helloWorld();

Импорт типов

TypeScript так же как и JavaScript использует npm-пакеты для зависимостей. При этом важно помнить, что в некоторых пакетах типов может и не быть. Например, в пакете lodash нет типов, поэтому при импорте его функций TypeScript будет ругаться на отсутствие типов.

Для решения этой проблемы нужно установить пакет @types/lodash, который содержит типы для lodash.

Но верна и обратная ситуация, например, пакет type-fest содержит только типы. Чтобы создать такой пакет самому и случайно не импортировать реализацию функций, нужно использовать специальный синтаксис:

// @file user.types.ts
export type User = { name: string };

// @file main.ts
import type { User } from './user.types';

Пространство имен (Namespace)

Модули решают проблему разнородных сущностей и коллизий с помощью разнесения кода по нескольким файлам. Чтобы коллизии не возникали в рамках одного файла, используют механизм пространств имен namespace:

namespace Hello {
  export function helloWorld() {
      console.log("Hello, world!");
  }
}

const helloWorld = Hello.helloWorld();

Больше всего этот механизм полезен авторам библиотек и оберток с типами @types/. Они заключают все интерфейсы в один namespace, совпадающий с названием библиотеки. Это гарантирует отсутствие коллизий имен и упрощает пользователям слияние интерфейсов. О последнем пункте поговорим в одном из следующих уроков курса.

Задание

Реализуйте namespace Company, в котором экспортируется функция isEmployeeEmail(). Функция принимает почту и домен. Если е-мейл пользователя содержит указанный домен, то функция возвращает true:

Company.isEmployeeEmail('tirion@hexlet.io', 'hexlet.io');
// true

Company.isEmployeeEmail('user@example.com', 'hexlet.io');
// false
Коммерческий опыт и Трудоустройство

Полезное

  • Официальная документация про модули

  • Как происходит Module Resolution

  • О модулях в JavaScript на Hexlet

  • Официальная документация про Namespaces

  • Метод includes()

Команда проекта находится в телеграм-сообществе. Там можно задать любой вопрос и повлиять на проект

Нашли ошибку? Есть что добавить? Пулреквесты приветствуются
/
Программирование
/
Курс Typescript
/

Система модулей

Typescript: Система модулей

В этом уроке рассмотрим систему модулей TypeScript, которая была создана до стандартизации ESM-модулей.

По умолчанию эта система модулей совместима с Node.js-модулями. Она использует идентичный алгоритм определения импортов и экспортов, при этом синтаксически похожа на ESM. В нем мы используем ключевые слова import/export для импортирования в текущий модуль и экспорта из него, при этом остается валидным использование CommonJS модулей.

Для примера создадим два файла. Из одного будем экспортировать функцию, а в другом импортировать ее:

// @file helloWorld.ts
export default function helloWorld() {
  console.log("Hello, world!");
}

// @file main.ts
import helloWorld from './helloWorld';

В системе модулей TypeScript также поддерживается именованный экспорт/импорт и импорт всего экспортированного через import * as:

// @file helloWorld
export function helloWorld() {}
export function helloWorldAgain() {}

// @file main
import { helloWorld, helloWorldAgain } from './helloWorld';

// @file next
import * as hw from './helloWorld';
hw.helloWorld();

Импорт типов

TypeScript так же как и JavaScript использует npm-пакеты для зависимостей. При этом важно помнить, что в некоторых пакетах типов может и не быть. Например, в пакете lodash нет типов, поэтому при импорте его функций TypeScript будет ругаться на отсутствие типов.

Для решения этой проблемы нужно установить пакет @types/lodash, который содержит типы для lodash.

Но верна и обратная ситуация, например, пакет type-fest содержит только типы. Чтобы создать такой пакет самому и случайно не импортировать реализацию функций, нужно использовать специальный синтаксис:

// @file user.types.ts
export type User = { name: string };

// @file main.ts
import type { User } from './user.types';

Пространство имен (Namespace)

Модули решают проблему разнородных сущностей и коллизий с помощью разнесения кода по нескольким файлам. Чтобы коллизии не возникали в рамках одного файла, используют механизм пространств имен namespace:

namespace Hello {
  export function helloWorld() {
      console.log("Hello, world!");
  }
}

const helloWorld = Hello.helloWorld();

Больше всего этот механизм полезен авторам библиотек и оберток с типами @types/. Они заключают все интерфейсы в один namespace, совпадающий с названием библиотеки. Это гарантирует отсутствие коллизий имен и упрощает пользователям слияние интерфейсов. О последнем пункте поговорим в одном из следующих уроков курса.

Задание

Реализуйте namespace Company, в котором экспортируется функция isEmployeeEmail(). Функция принимает почту и домен. Если е-мейл пользователя содержит указанный домен, то функция возвращает true:

Company.isEmployeeEmail('tirion@hexlet.io', 'hexlet.io');
// true

Company.isEmployeeEmail('user@example.com', 'hexlet.io');
// false
Коммерческий опыт и Трудоустройство

Полезное

  • Официальная документация про модули

  • Как происходит Module Resolution

  • О модулях в JavaScript на Hexlet

  • Официальная документация про Namespaces

  • Метод includes()

Команда проекта находится в телеграм-сообществе. Там можно задать любой вопрос и повлиять на проект

Нашли ошибку? Есть что добавить? Пулреквесты приветствуются
← ПредыдущийСледующий →
← ПредыдущийСледующий →
← ПредыдущийСледующий →

Ваше упражнение проверяется по этим тестам

import { expect, test } from 'vitest';
import authorize from './index';

test('function', () => {
  expect(authorize({ email: 'test@hexlet.io' })).toBe(true);
  expect(authorize({ email: 'hexlet.io@example.com' })).toBe(false);
  expect(authorize({ email: 'test@example.com' })).toBe(false);
  expect(authorize(null)).toBe(false);
});
← ПредыдущийСледующий →

Решение учителя откроется через:

20:00

waiting_clock
← ПредыдущийСледующий →