Модуль vs Пространство имен - Импорт против Требуется Typescript

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

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

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

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

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

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

 Dan Pantry30 июл. 2016 г., 18:19
это имеет много внимания, которое отвечает на ваш вопрос, не уверен, почему он был навязчивым
 Reddy01 авг. 2016 г., 06:30
@DanPantry, до запуска Баунти не было ни одного ответа :(
 Dan Pantry01 авг. 2016 г., 09:56
Моя ошибка - я не сравнивал временные метки.

Ответы на вопрос(4)

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

 Shai Petel26 июл. 2017 г., 18:00
Именно так. Так запутанно, и так мало информации об этом, говоря, что это в основном то же самое. Интересно, почему это было отклонено?
модуль для внешних пакетов 2. пространство имен для внутренних пакетов

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

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

Больше

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

 Reddy27 июл. 2016 г., 05:34
извините, чтобы сообщить, вопросы без ответа. Я ожидал, что объясню подробно с помощью примера из реального мира, а не из определения учебника.
 M9816 февр. 2017 г., 11:35
Вы имеете в виду, что в TypeScript нет модульной клавиатуры?

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

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

Это почти устаревшее понятие. До появления модулей 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.

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

 Kokodoko02 июн. 2017 г., 13:57
При этом ... Мои модули компилируются, но не будут выполняться после SystemJS.import ('/ js / main.js'); Есть идеи, как «запустить» приложение?
 Paleo02 июн. 2017 г., 12:50
@ Кокодоко Ты прав! Виноват! Похоже компилятор TypeScriptможно построить связку начиная с TS 1.8Я пропустил функцию.
 Kokodoko02 июн. 2017 г., 11:48
Хм ... какая разница? .... Я использую модули и только TSC для создания одного файла .js. Мне не нужно использовать systemJS, webpack или browserify.
 Paleo01 июн. 2017 г., 16:41
@ Kokodoko, Нет. Это может просто объединить.
 Kokodoko01 июн. 2017 г., 14:55
Разве компилятор машинописного текста автоматически не объединяет модули в один файл .js?
Решение Вопроса

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

Пространства имен используются для организации / инкапсуляции вашего кода. Внешние модули используются для организации / инкапсуляции вашего кода и для определения местоположения вашего кода во время выполнения. На практике у вас есть два варианта во время выполнения: 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 - это все, что находится в глобальном пространстве), экспортируйте только интерфейсы и используйте внедрение зависимостей AngularJS для реализации. доступны для использования. Поместите все классы в корень каталога, добавьте 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);
})();

Ваш ответ на вопрос