The module system is an interesting feature of TypeScript, the statically typed superset of JavaScript.
Modules provide the possibility to group related logic, encapsulate it, structure your code and prevent pollution of the global namespace.
Modules can provide functionality that is only visible inside the module, and they can provide functionality that is visible from the outside using the export
keyword.
TypeScript’s module system comes in two flavors: internal and external modules.
In this blogpost I’m going to explain how to provide and consume both internal and external TypeScript modules.
A comparison of internal and external modules
Internal modules are TypeScript’s own approach to modularize your code. Internal modules can span across multiple files, effectively creating a namespace.
In the generated JavaScript, internal modules will materealize as implementations of the module design pattern.
There is no runtime module loading mechanism, so – in a browser environment – you have to load the modules using <script/> tags on your own. Alternatively, you can compile all TypeScript files into one big JavaScript file that you include using a single <script/> tag.
External modules leverage a runtime module loading mechanism. You have the choice between CommonJS and AMD.
CommonJS is used by node.js, whereas RequireJS is a prominent implementation of AMD often used in browser environments.
When using external modules, files become modules. The modules can be structured using folders and sub folders.
Working with internal modules
How to provide internal modules
To create an internal module, we use the module
keyword with a module name.
Classes, interfaces, functions and variables in the module’s body will be visible to the outside of the module if you put an export
keyword right in front of them.
module mymod { export function doSomething() { // this function can be accessed from outside the module } export class ExportedClass { // this class can be accessed from outside the module } class AnotherClass { // this class can only be accessed from inside the module } }
For nesting modules, you can either use a dot notation for the module name
module mymod.submod { // ... }
or you can nest module statements
module mymod { module submod { // ... } }
How to consume internal modules
You can either use classes from internal modules by addressing them using their fully qualified name, or using an import
statement.
Here is an example that shows how to use classes from a module by addressing them with their fully qualified name:
var exportedClassInstance = new mymod.ExportedClass();
Here is another example that uses the import
keyword:
import ExportedClass = mymod.ExportedClass; var exportedClassInstance = new ExportedClass();
In fact, this simply creates an alias for the fully qualified class. You could even use another name for the imported class, as shown below.
import ExpCl = mymod.ExportedClass; var exportedClassInstance = new ExpCl();
Working with external modules
How to provide external modules
If you want to use external modules, you have to decide which module system (AMD or CommonJS) to use and then compile your sources using the --module
compiler flag. Possible values are amd
or commonjs
.
You don’t have to use the module
keyword in external modules, as the file’s name and path will create the namespace.
Again, classes, interfaces, functions and variables with the export
keyword in front of them will be visible to the outside of the module.
export function doSomething() { // this function can be accessed from outside the module } export class ExportedClass { // this class can be accessed from outside the module } class AnotherClass { // this class can only be accessed from inside the module }
If you go with the one class per file best practice, it’s recommended to use a single export=
statement.
This makes consuming these external modules easier (see How to consume external modules).
The export=
statement turns the exported object into the module.
class ExportedClass { // this class can be accessed from outside the module } export = ExportedClass;
How to consume external modules
If you have used the export=
statement in the exported module, you can use the external module as shown below.
import ExportedClass = require("mymod/ExportedClass"); var exportedClassInstance = new ExportedClass();
Please note that you call require() with the filename of the module (and optionally with a path).
If you have not used the export=
statement, e.g. because you put multiple external classes into one file, you would import the module (in this case a file named “mymod.ts”) and have to access the class of the module via a dot notation as shown below.
import mymod = require("mymod"); var exportedClassInstance = new mymod.ExportedClass();
How to consume external JavaScript libraries using the require keyword
In general, the require(FILENAME) call will look for a TypeScript file called FILENAME.
If you want to use a JavaScript library using e.g. RequireJS, you have to give the compiler a hint that it doesn’t have to look for a TypeScript file on the filesystem.
You do this with the declare module
statement. Here is an example from the underscore declaration file from DefinitelyTyped.
declare var _: UnderscoreStatic; declare module "underscore" { export = _; }
Now you can consume the library with a require
statement.
import _ = require("underscore");
Einsortiert unter:Web as a Platform Tagged: AMD, CommonJS, modules, node.js, requirejs, TypeScript
