Подтвердить что ты не робот

Module vs Namespace - Импорт vs Требовать Typescript

Я получаю много путаницы с module/namespace/export и import, require, reference usage. Находясь на фоне Java, может ли кто-нибудь объяснить мне в двух словах, когда использовать то, что и какой правильный дизайн? Я чувствую, что я возился, когда пишу образец проекта

Пока это мое понимание 1. module для внешних пакетов 2. namespace предназначен для внутренних пакетов

  • Я не понял, как мы их классифицируем?
  • Когда экспортировать класс или пространство имен или пакет?
  • Если мы экспортируем пакет/пространство имен, все классы внутри них экспортируются или должны быть явно экспортированы
  • Как каждый из них может быть импортирован/необходим?

Согласно документу, если я создаю каждый файл ts для каждого менеджера/модели, TypScript не рекомендует использовать "пространства имен"? Непосредственно использовать ссылочные пути?

Пожалуйста, объясните подробно, поскольку я прихожу из разных источников и не уверен в ES6/ES5 и т.д. ".

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

4b9b3361

Ответ 1

Я не понял, как мы классифицируем их?

Пространства имен используются для организации/инкапсуляции кода. Внешние модули используются для организации/инкапсуляции кода и определения местоположения вашего кода во время выполнения. На практике у вас есть два варианта во время выполнения: 1) объединить весь преобразованный код в один файл или 2) использовать внешние модули и иметь несколько файлов и потребовать какой-то другой механизм для доступа к этим файлам.

Когда экспортировать класс или пространство имен или пакет?

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

Если мы экспортируем пакет/пространство имен, все классы внутри них экспортируются или должны быть явно экспортированы

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

Как каждый из них может быть импортирован/необходим?

Это зависит от того, используете ли вы внешние модули. Внешнему модулю всегда нужно импортировать его для "использования". Импорт пространства имен, который не во внешнем модуле, действительно просто предоставляет псевдоним для пространства имен - вам все равно придется префикс типа/все с псевдонимом (и именно поэтому вы, как правило, не хотите использовать пространства имен с внешними модулями; это означает, что вам всегда нужно использовать префикс при обращении к чему-либо, предоставленному внешним модулем.) Пространства имен, которые не находятся во внешнем модуле, могут охватывать файлы, поэтому, если вы находитесь в одном и том же пространстве имен, вы можете ссылаться на все, что экспортировано пространство имен, не требующее какого-либо импорта.

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

Справочные директивы используются во время компиляции для поиска информации о типе. У вашего источника есть определенный символ. Как компилятор TypeScript определяет определение для этого символа? Справочная директива в основном была включена в механизм tsconfig.json - используя tsconfig.json, вы сообщаете компилятору, где находятся все ваши источники.

Пространства имен могут содержать определения типов и/или реализацию. Если пространство имен содержит только информацию о типе, то оно вообще не имеет проявления во время выполнения - вы можете проверить это, посмотрев на вывод JS и найдя пустой файл JS. Если пространство имен имеет код реализации, тогда код завершается внутри замыкания, которое назначается глобальной переменной с тем же именем, что и пространство имен. При вложенных пространствах имен будет глобальная переменная для пространства имен корней. Опять же, проверьте выход JS. Пространства имен исторически являются тем, как клиентские библиотеки JS пытались избежать проблемы с коллизиями имен. Идея состоит в том, чтобы обернуть всю вашу библиотеку в одно закрытие, а затем выявить как можно больший глобальный след - только одну глобальную переменную, ссылающуюся на закрытие. Ну, проблема в том, что вы заявили имя в глобальном пространстве. Что, если вы хотите, скажем, две версии библиотеки? Пространство имен TypeScript по-прежнему содержит вопрос о том, как найти источник для пространства имен. То есть исходный код, который ссылается на A.B, все еще имеет проблему, говорящий компилятору, как найти A.B - либо с помощью ссылочных директив, либо с помощью tsconfig.json. Или путем помещения пространства имен во внешний модуль и затем импорта внешнего модуля.

Внешние модули возникли на стороне сервера JS. Между внешним модулем и файлом файловой системы существует взаимно однозначное соответствие. Вы можете использовать структуру каталогов файловой системы для организации внешних модулей во вложенную структуру. Импорт внешнего модуля, как правило, приводит к зависящей от времени выполнения внешнему модулю (исключение - это когда вы импортируете внешний модуль, но затем не используете какой-либо его экспорт в позиции значения, то есть вы импортируете только внешний модуль чтобы получить информацию о своем типе). Внешний модуль неявно находится в замыкании, и это ключ: пользователь модуля может назначить замыкание любой локальной переменной, которую они хотят. TypeScript/ES6 добавляет дополнительный синтаксис вокруг сопоставления экспорта внешних модулей с локальными именами, но это просто тонкость. На стороне сервера размещение внешнего модуля относительно прямо: просто найдите файл, представляющий внешний модуль в локальной файловой системе. Если вы хотите использовать внешние модули на стороне клиента, в браузере он становится более сложным, так как нет эквивалента файловой системе, у которой есть модуль, доступный для загрузки. Итак, теперь на стороне клиента вам нужен способ объединить все эти файлы в форму, которую можно использовать удаленно в браузере - вот где такие модули, как Webpack (Webpack делает чертовски много больше, чем пакеты модулей) и Browserify вступает в игру. Модульные модули позволяют выполнять во время работы внешние модули в браузере.

Сценарий реального мира: AngularJS. Притвориться, что внешние модули не существуют, используйте единое пространство имен для ограничения загрязнения глобального пространства (в примере ниже одна переменная MyApp - это все, что есть в глобальном пространстве), только экспортные интерфейсы и использование AnggleJS-зависимой инъекции для выполнения реализаций доступный для использования. Поместите все классы в корне каталога, добавьте tsconfig.json в корневой каталог, установите шаблоны angularjs под одним и тем же корнем каталога, чтобы tsconfig.json тоже его подбирал, объединив все выходные данные в один JS файл. Это будет отлично работать для большинства проектов, если повторное использование кода не вызывает большого беспокойства.

MyService.ts:

namespace MyApp {

    // without an export the interface is not visible outside of MyService.ts
    export interface MyService { 
        ....
    }

    // class is not exported; AngularJS DI will wire up the implementation
    class MyServiceImpl implements MyService {
    }

    angular.module("MyApp").service("myService", MyServiceImpl);
}

MyController.ts:

namespace MyApp {

   class MyController {
       // No import of MyService is needed as we are spanning 
       // one namespace with multiple files.
       // MyService is only used at compile time for type checking. 
       // AngularJS DI is done on the name of the variable. 
       constructor(private myService: MyService) { 
       }
   }
   angular.module("MyApp").controller("myController", MyController);
}

Использование IIFE, чтобы избежать загрязнения глобальной области выполнения. В этом примере глобальные переменные вообще не создаются. (Предполагается, что tsconfig.json.)

Foo.ts:

namespace Foo {
    // without an export IFoo is not visible. No JS is generated here
    // as we are only defining a type.
    export interface IFoo {
        x: string;
    }
}

interface ITopLevel {
    z: string;
}

(function(){
    // export required above to make IFoo visible as we are not in the Foo namespace
    class Foo1 implements Foo.IFoo {
        x: string = "abc";
    }
    // do something with Foo1 like register it with a DI system
})();

Bar.ts:

// alias import; no external module created
import IFoo = Foo.IFoo;

(function() {

    // Namespace Foo is always visible as it was defined at
    // top level (outside of any other namespace).
    class Bar1 implements Foo.IFoo {
        x: string;
    }

    // equivalent to above
    class Bar2 implements IFoo {
        x: string;
    }

    // IToplevel is visible here for the same reason namespace Foo is visible
    class MyToplevel implements ITopLevel {
        z: string;
    }

})();

Используя IIFE, вы можете исключить введение MyApp в качестве глобальной переменной в первом примере.

MyService.ts:

interface MyService { 
    ....
}

(function() {

    class MyServiceImpl implements MyService {
    }

    angular.module("MyApp").service("myService", MyServiceImpl);
})();

MyController.ts:

(function() { 

   class MyController { 
       constructor(private myService: MyService) { 
       }
   }

   angular.module("MyApp").controller("myController", MyController);
})();

Ответ 2

Есть две вещи:

  • Модуль в TypeScript является стандартным понятием ES6, он использует ключевые слова import/export на верхнем уровне кода;
  • Пространство имен - это понятие, специфичное для TypeScript, чтобы помочь упорядочить код устаревшим способом.

Namespaces

Это почти устаревшее понятие. До модулей ES6 общим способом разделения кода JavaScript в браузере было создание глобальных переменных. Например, все функции API, такие как подчеркивание, были расположены в глобальной переменной с именем _.

Этот старый способ продолжения похож на пакеты Java или пространства имен PHP. Он не адаптирован к Интернету. Новый стандарт ECMAScript решает такие проблемы, как: как использовать две библиотеки с одинаковым именем? Как использовать две разные версии одной и той же библиотеки?

Примечание. В версиях TypeScript до определения ECMAScript "модулей" (лето 2014) пространства имен назывались "внутренними модулями", а модули назывались "внешними модулями".

Примечание 2: ключевое слово export внутри namespace является нестандартным TypeScript использованием ключевого слова. Это средство для объявления вещи, которая является общедоступной из-за пределов пространства имен.

Модули ES6

Модуль - это файл, содержащий ключевые слова import или export на верхнем уровне кода.

TypeScript следует стандарту из ECMAScript. Я предлагаю прочитать хорошее введение в модули ES6 в статье из Mozilla.

Если вы хотите использовать модули во внешнем приложении (в браузере), вам придется использовать пакет (Webpack [документация здесь], Browserify) или загрузчик (SystemJS [учебник здесь], RequireJS) и настроить TypeScript в этой среде.

Если ваш код выполнен в Node.js, просто настройте компилятор TypeScript для создания формата CommonJS.

Примечание: пространство имен может быть объявлено в модуле. В этом случае он не будет доступен как глобальная переменная извне модуля. Однако он может быть экспортирован из модуля.

Ответ 3

  • модуль предназначен для внешних пакетов. 2. пространство имен для внутренних пакетов.

На самом деле ключевое слово module заменено ключевым словом namespace.

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

Подробнее

Надеюсь, это поможет дальше: https://basarat.gitbooks.io/typescript/content/docs/project/modules.html

Ответ 4

" требуют" и " импорт" эквивалентны по функциональности. мы можем использовать их как взаимозаменяемо, потому что у нас есть транспилеры, которые не заботятся о том, поддерживает ли браузер их изначально или нет. но в то время как " требуется" имеет свои корни в старом стиле кодирования, идущем от CommonJS до 2009 года, "import" выводит свой синтаксис из широко распространенного синтаксиса ES6 (ES2015). поэтому для новых проектов следует использовать " import", а не " требуется".