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

Какая разница между внутренними и внешними модулями в TypeScript?

Я потратил некоторое время на изучение спецификации языка Typescript и немного смущен насчет разницы между внутренними и внешними модулями. Вот описание, взятое непосредственно из спецификации:

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

Внешние модули (раздел 9.4) представляют собой отдельно загруженные тела кода, на которые ссылаются имена внешних модулей. Внешний модуль записывается как отдельный исходный файл, содержащий хотя бы одно объявление импорта или экспорта. Кроме того, внешние модули могут быть объявлены с использованием AmbientModuleDeclarations в глобальном модуле, который напрямую определяет имена внешних модулей в виде строковых литералов. Это описано далее в разделе 0.

Из того, что я понял, я думаю, что внешние модули соответствуют файлам Typescript без включения определений модулей, которые просто экспортируют набор типов и/или переменных. Из другого файла Typescript я могу просто импортировать внешний модуль в foo.ts с помощью import foo = module("foo");

Может кто-нибудь объяснить мне различие между внешними и внутренними модулями?

4b9b3361

Ответ 1

Разделы 9.3 и 9.4 спецификации объясняют это более четко. Здесь я воспроизведу некоторые примеры, приведенные в этих разделах.

Внешние модули

Предположим, что следующий код находится в main.ts.

import log = module("log");
log.message("hello");

Этот файл ссылается на внешний модуль log, определенный любым экспортом log.ts.

export function message(s: string) { 
  console.log(s); 
}

Обратите внимание, что log.ts не использует ключевое слово module. Он просто экспортирует вещи с помощью export.

Внутренние модули

Этот файл имеет два внутренних модуля, X.Y.Z.

module A.B.C { 
  import XYZ = X.Y.Z; 
  export function ping(x: number) { 
    if (x > 0) XYZ.pong(x – 1); 
  }
} 
module X.Y.Z { 
  import ABC = A.B.C; 
  export function pong(x: number) { 
    if (x > 0) ABC.ping(x – 1); 
  } 
}

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

Ответ 2

Согласно представлениям Андерса: http://channel9.msdn.com/posts/Anders-Hejlsberg-Introducing-TypeScript (34:40) и Typescript документация, внешние модули - это модули, основанные на top AMD (определение асинхронной модели) или CommonJS.

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

Предположим, что у вас есть класс Main с определенным методом log, помещенным в файл transfer.js. Внутренние методы класса Main видны только при импорте файла transfer.js в верхней части исходного файла js следующим образом: ///<reference path="transfer.js"/>. Таким образом, компилятор устраняет обход всех файлов js во время выполнения.

Это огромное преимущество использования внешних модулей. Другой - когда вы пытаетесь ссылаться на внешний метод или класс, который в нормальном потоке javascript сверху вниз определяется позже, чем вызов метода. Использование внешних модулей ссылочный класс создается только при вызове метода.

Ответ 3

Внутренний модуль:

  • Вы можете определять модули в файлах typescritp.
  • Все переменные, определенные в модуле, привязаны к модулю и удаляются из глобальной области.
  • Когда вы компилируете свои файлы typescript, ваши модули преобразуются в переменные, которые гнездятся при необходимости для создания объектов, похожих на пространство имен. Обратите внимание, что класс, определенный в модуле, аккуратно изолирован с помощью выражения IIFE (выражение с выведенной функцией).
  • В приведенном ниже коде показано, что переменная MyClass привязана к модулю MyInternalModule. Они не могут быть доступны за пределами модуля, поэтому последняя строка кода показывает, что ошибка не может найти имя MyClass.
  • Вы можете получить доступ к переменной вне модуля, используя ключевое слово export.
  • Вы также можете расширять внутренние модули, делиться ими по файлам и ссылаться на них с помощью синтаксиса с тройной косой чертой. (///)

Пример:

module MyInternalModule{  
    class MyClass{               //if We write export keyword before the MyClass then last line works fine
        constructor (
            public height: number, 
            public width: number) {
    }
    }                   
    //working properly
    var obj1 = new MyClass(10, 4);
}

// it wont work //Because the out of the scope
var obj2 = new MyInternalModule.MyClass(10,4) //shows error: can not find name MyClass

Скомпилированная версия typescript:

var MyInternalModule;
(function (MyInternalModule) {
    var MyClass = (function () {
        function MyClass(height, width) {
            this.height = height;
            this.width = width;
        }
        return MyClass;
    })();
    //working properly
    var obj1 = new MyClass(10, 4);
})(MyInternalModule || (MyInternalModule = {}));

Внешний модуль:

Пример:

// bootstrapper.ts file

// imports the greeter.ts file as the greeter module
import gt = module('greeter');  
export function run() {  
    var el = document.getElementById('content');
    var greeter = new gt.Greeter(el);
    greeter.start(); 
}

// greeter.ts file

// exports the entire module
export class Greeter {  
    start() {
         this.timerToken = setInterval(() => 
             this.span.innerText = 
             new Date().toUTCString(), 500);
    }
}