Valentin
Valentin

Reputation: 8074

What's the difference between internal and external modules in TypeScript?

I have spent some time reading the Typescript language specification and am somewhat confused about the difference between internal and external modules. Here is the description taken directly from the specification:

Internal modules (section 9.2.2) are local or exported members of other modules (including the global module and external modules). Internal modules are declared using ModuleDeclarations that specify their name and body. A name path with more than one identifier is equivalent to a series of nested internal module declarations.

External modules (section 9.4) are separately loaded bodies of code referenced using external module names. An external module is written as a separate source file that contains at least one import or export declaration. In addition, external modules can be declared using AmbientModuleDeclarations in the global module that directly specify the external module names as string literals. This is described further in section 0.

From what I've understood I think that external modules correspond to typescript files without enclosing module definitions that simply export a set of types and/or variables. From another typescript file I can simple import an external module in foo.ts with import foo = module("foo");

Can somebody explain to me the destinction between external and internal modules?

Upvotes: 44

Views: 22071

Answers (4)

Yogesh Umesh Vaity
Yogesh Umesh Vaity

Reputation: 48119

Internal Modules: namespace or module keyword

Declaration

An Internal module can be declared using either the namespace or the module keyword. Then we can decide which part of our internal module to make public using the export keyword.

// LivingThings.ts
export namespace Animals {
    export class Dog { }
    export class Cat { }
}
export namespace Plants {
    export class Orchid { }
    export class Bamboo { }
}

// LivingThingsUser.ts
import { Animals, Plants } from "./LivingThings"

Logical Grouping

Before ES6, internal modules were used in Typescript for encapsulating the interfaces, classes, functions and variables to support a group of related functionalities and hide implementation details. This way we could prevent variables from leaking into the global space. This helped in better code organisation and prevent name collisions. Now it is recommended to use external modules (ES6 modules) to achieve this.

The internal modules are now used for ambient namespace declarations.

Single File Usage

We can declare internal modules across multiple files and they can be concatenated using --outFile flag. We can then use that concatenated file inside the <script> tag in our HTML page. This allows us to structure our code in a good way in a client-side web application with all dependencies included.


External Modules: just export and import keywords

Declaration

External Modules are also called ES6 modules. We use multiple files for grouping related functionalities and just use the export keyword to make the desired object publicly visible.

// Animals.ts
export class Dog { }
export class Cat { }

// Plants.ts
export class Orchid { }
export class Bamboo { }

// LivingThingsUser.ts
import { Dog, Cat } from "./Animals"
import { Orchid, Bamboo } from "./Plants"

Logical Grouping

The logical grouping is achieved by using separate files for grouping related functionalities. For this reason, the external modules are also called file modules.

Single File Usage

We don't load the external modules of the client-side web application using the <script> tag, because the browsers may get sluggish while downloading so many files and rendering the page at the same time. For this, we use the module loaders like the CommonJS, AMD, SystemJS that enable us to load files asynchronously or concatenate the external module files into a single optimized file.

For server-side, especially in Node.js, the external modules are strongly recommended.


Nomenclature

For declaring the internal modules, the typescript team recommends using the namespace { } instead of the module { } syntax to avoid confusion with the external modules. Because the external modules are now simply 'modules' and internal modules are 'namespaces'.

That's it!

Upvotes: 1

vsjondhale
vsjondhale

Reputation: 21

Internal Module:

  1. You can define modules within your typescritp files.
  2. All variables defined within the module are scoped to the module and removed from the global scope.
  3. When you compile your typescript files your modules are converted into variables that nest as necessary to form namespace-like objects. Notice that the class defined within the module is neatly isolated using an IIFE (Immediately Invoked Function Expression).
  4. The code below shows that the MyClass variable scoped to the MyInternalModule module. They cannot be accessed outside of the module that’s why the final line of the code shows the error can not find name MyClass.
  5. You can access the variable outside the module using the export keyword.
  6. You can also extend internal modules, share them across files, and reference them using the triple slash syntax.( /// )

Example:

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

Compiled Version of 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 = {}));

External Module:

Example:

// 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);
    }
}

Upvotes: 2

Endre Simo
Endre Simo

Reputation: 11551

According to Anders presentations: http://channel9.msdn.com/posts/Anders-Hejlsberg-Introducing-TypeScript (34:40) and Typescript documentation, the external modules are modules which are based on top AMD (Asynchronous Model Definition) or CommonJS.

External modules are useful in sense they hide the internal statements of the module definitions and show only the methods and parameters associated to the declared variable.

Suppose you have a Main class with a defined log method placed in a transfer.js file. The internal methods of the Main class are only visible when you are importing the transfer.js file at the top of the source js file as so: ///<reference path="transfer.js"/>. This way the compiler eliminates the traversal of all js files at runtime.

This is a huge benefit of using external modules. Another one is when you are trying to reference an external method or class which in the normal top-down javascript flow is defined later than the method invocation. Using external modules the referenced class is instantiated only on method invocation.

Upvotes: 7

Peter Olson
Peter Olson

Reputation: 142921

Sections 9.3 and 9.4 of the specification explain this more clearly. I'll reproduce here some of the examples given in those sections.

External modules

Suppose the following code is in main.ts.

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

This file references an external module log, defined by whatever log.ts exports.

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

Notice that log.ts doesn't use the module keyword anywhere. It just exports things with export.

Internal modules

This file has two internal modules, 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); 
  } 
}

These behave (mostly) like external modules, but they are contained in one file and you don't have to reference any outside files to use them. They have to be contained inside of a module block when they are defined.

Upvotes: 28

Related Questions