Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Чим namespace відрізняється від ES-модуля і що сталося з ключовим словом module у TypeScript 7?

Простори імен (namespaces) з'явилися в TypeScript до того, як JavaScript отримав ES-модулі. Вони групують код в іменований об'єкт у глобальній області:

namespace Validation {
  export function isEmail(value: string): boolean {
    return value.includes('@');
  }
}

Validation.isEmail('a@b.ua');

Компілюються в IIFE, що створює об'єкт Validation.

ES-модулі - стандарт JavaScript: файл = модуль, явні import/export, власна область видимості, підтримка браузерами, Node.js і збирачами.

Чому для коду застосунку - модулі, а не namespaces:

  • збирачі розуміють залежності між модулями - tree shaking, розділення коду. Простір імен - один об'єкт, з якого нічого не викинеш;
  • явні залежності видно з імпортів; простори імен покладаються на порядок підключення файлів;
  • стирання типів (Node.js, erasableSyntaxOnly) не підтримує namespaces з виконуваним кодом - їм потрібна генерація;
  • outFile, що склеював простори імен з багатьох файлів в один, видалено в TypeScript 6.

Де namespaces лишилися доречними:

  • у файлах декларацій - для опису бібліотек, що створюють глобальні об'єкти, і для поєднання функції з властивостями (злиття з функцією чи класом);
  • простори імен лише з типами (namespace API { export type User = ... }) - стираються без генерації коду, хоча й тут частіше обходяться модулями;
  • доповнення глобальних просторів: declare global { namespace Express { ... } }, namespace NodeJS.

Ключове слово module для просторів імен: колись простір імен можна було оголосити як module Foo { }. Згодом з'явилося namespace, а module лише не радили. У TypeScript 6 це стало помилкою з можливістю тимчасово приглушити її, у TypeScript 7 - остаточною помилкою:

module Legacy { }      // помилка: використовуйте namespace
namespace Modern { }   // правильно
declare module 'some-lib' { }   // це інше - ambient-оголошення модуля, і воно підтримується

Причина - можлива пропозиція «module blocks» до стандарту JavaScript, з якою старий синтаксис TypeScript конфліктував би.

Міграція старого коду з просторами імен на модулі зазвичай механічна: кожен простір імен - окремий файл з export, звернення Validation.isEmail - імпорт import { isEmail } from './validation.js' або import * as Validation from ....

Докладніше в документації: Простори імен і модулі

Схожі питання