What's the difference between internal and external modules in TypeScript?
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.
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.
Internal Module:
- You can define modules within your typescritp files.
- All variables defined within the module are scoped to the module and removed from the global scope.
- 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).
- 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.
- You can access the variable outside the module using the export keyword.
- 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);
}
}