I have spent some time reading the Typescript language specification and am somewhat confused about the difference between internal and external
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.
namespace or module keywordDeclaration
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.
export and import keywordsDeclaration
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.
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!
Internal Module:
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);
}
}
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.
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.
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.