Spec-Zone.ru › TypeScript 5.1

Пространства имен и модули

В этой статье описаны различные способы организации кода с помощью модулей и пространств имен в TypeScript. Мы также рассмотрим некоторые продвинутые темы по использованию пространств имен и модулей и коснемся некоторых распространенных ошибок при их использовании в TypeScript.

См. документацию по Модулям для получения дополнительной информации об ES-модулях. См. документацию по Пространствам имен для получения дополнительной информации о пространствах имен TypeScript.

Примечание: в очень старых версиях TypeScript пространства имен назывались «Внутренними модулями»; они предшествуют системам модулей JavaScript.

Использование модулей

Модули могут содержать как код, так и объявления.

Модули также зависят от загрузчика модулей (такого как CommonJs/Require.js) или среды выполнения, поддерживающей ES-модули. Модули обеспечивают лучшую повторную используемость кода, более сильную изоляцию и лучшую поддержку инструментов для объединения.

Также следует отметить, что для приложений Node.js модули являются по умолчанию, и мы рекомендуем использовать модули вместо пространств имен в современном коде.

Начиная с ECMAScript 2015, модули являются встроенной частью языка и должны поддерживаться всеми реализациями совместимых движков. Таким образом, для новых проектов модули будут рекомендуемым механизмом организации кода.

Использование пространств имен

Пространства имен — это специфичный для TypeScript способ организации кода.
Пространства имен — это просто именованные объекты JavaScript в глобальном пространстве имен. Это делает пространства имен очень простым конструктом в использовании. В отличие от модулей, они могут охватывать несколько файлов и могут быть объединены с помощью outFile. Пространства имен могут быть хорошим способом структурировать ваш код в веб-приложении, с включением всех зависимостей в виде тегов <script> в вашем HTML-странице.

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

Недостатки пространств имен и модулей

В этом разделе мы опишем различные распространенные недостатки использования пространств имен и модулей и способы их предотвращения.

/// <reference>-ия модуля

Распространённая ошибка — попытка использовать синтаксис /// <reference ... /> для ссылки на файл модуля вместо использования инструкции import. Чтобы понять разницу, нам сначала нужно понять, как компилятор может найти информацию о типе для модуля на основе пути к файлу import (например, путь к файлу ... в import x from "...";, import x = require("...");, и т. д.).

Компилятор будет пытаться найти .ts, .tsx, а затем .d.ts с соответствующим путём. Если определённый файл не найден, компилятор будет искать *декларацию модуля с указанием среды*. Обратите внимание, что эти декларации необходимо объявлять в файле .d.ts.

  • myModules.d.ts

    // In a .d.ts file or .ts file that is not a module:
    declare module "SomeModule" {
      export function fn(): string;
    }
  • myOtherModule.ts

    /// <reference path="myModules.d.ts" />
    import * as m from "SomeModule";

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

Излишнее использование пространств имен

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

  • shapes.ts

    export namespace Shapes {
      export class Triangle {
        /* ... */
      }
      export class Square {
        /* ... */
      }
    }

В этом случае пространство имен верхнего уровня Shapes оборачивает Triangle и Square без причины. Это запутывает и раздражает потребителей вашего модуля:

  • shapeConsumer.ts

    import * as shapes from "./shapes";
    let t = new shapes.Shapes.Triangle(); // shapes.Shapes?

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

Ещё раз, почему не стоит пытаться использовать пространство имен для содержимого модуля: основная идея использования пространств имен — обеспечить логическое группирование конструкций и предотвратить конфликты имён. Поскольку сам файл модуля уже является логической группировкой, а его имя верхнего уровня определяется кодом, который его импортирует, нет необходимости использовать дополнительный уровень модуля для экспортируемых объектов.

Вот пересмотренный пример:

  • shapes.ts

    export class Triangle {
      /* ... */
    }
    export class Square {
      /* ... */
    }
  • shapeConsumer.ts

    import * as shapes from "./shapes";
    let t = new shapes.Triangle();

Компромиссы при использовании модулей

Так же, как существует взаимно однозначное соответствие между файлами JS и модулями, TypeScript имеет взаимно однозначное соответствие между файлами исходного кода модуля и генерируемыми файлами JS. Одним из последствий этого является то, что нельзя объединять несколько файлов исходного кода модулей в зависимости от системы модулей, к которой вы обращаетесь. Например, вы не можете использовать опцию outFile при использовании целевых систем commonjs или umd, но с TypeScript 1.8 и более поздними версиями, возможно использование outFile при использовании целевых систем amd или system.

© 2012-2023 Microsoft
Licensed under the Apache License, Version 2.0.
https://www.typescriptlang.org/docs/handbook/namespaces-and-modules.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API