Reputation: 8074
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
Reputation: 48119
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!
Upvotes: 1
Reputation: 21
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);
}
}
Upvotes: 2
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
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.
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.
Upvotes: 28