TypeScript Modules



Headlines
Principle

By using export and import (a.k.a. EcmaScript Module -ESM-), TypeScript unifies the way modules depend upon each other. For example, Node.js ☛ require keyword (a.k.a. "CommonJS" module) is no longer useful and thus used in TypeScript.

Based on the value of module key in tsconfig.json (e.g., "module": "CommonJS"), TypeScript generates JavaScript code following a module system standard: "CommonJS", "ES6", "ESNext", or any other.

Inline code

Rule(s)

Example

<!DOCTYPE html>
<html>
    <head>
        …
        <script src="js/chai.js"></script>
        <script src="js/dat.gui.min.js"></script>
        <!-- Loading based on Content Delivery Network -CDN-: -->
        <script src="https://code.createjs.com/createjs-2015.11.26.min.js"></script>
        <!-- My stuff: -->
        <script src="js/Homemade_code.js"></script>
        <script>
            if (typeof chai === "undefined")
                window.alert("STOP: it won't work because 'chai.js' has not been loaded…");
            if (typeof dat === "undefined")
                window.alert("STOP: it won't work because 'dat.gui.min.js' has not been loaded…");
            if (typeof createjs === "undefined")
                window.alert("STOP: it won't work because 'createjs-2015.11.26.min.js' has not been loaded…");
            window.onload = go; // 'go' function must exist in 'js/Homemade_code.js' file...
        </script>
    </head>
    <body >
        <canvas id="my_canvas" width="600" height="400"></canvas>
    </body>
</html>
Content Delivery Network -CDN-

Nice Web sites for Content Delivery Network -CDN- are cdnjs, jsdelivr, or unpkg.

Example

<!DOCTYPE html>
<html>
    <head>
        …
        <script type="module">
            import {
                unaryTest,
                evaluate
            } from 'https://unpkg.com/feelin@3.0.0?module';
            console.log(unaryTest('1', { '?': 1 }));
        </script>
    </head>
    <body >
        …
    </body>
</html>
export and import

Rule(s)

Example (PURE JavaScript, using RequireJS)

<!-- 'data-main' attribute tells 'require.js' to load 'UV_mapping_three.js' after 'require.js' loads... -->
<!-- *By construction*, 'UV_mapping_three.js' is loaded in an asynchronous way by 'require.js' -->
<!-- Here, 'async' just embodies the asynchronous loading of 'require.js' itself! -->
<script async data-main="./js/UV_mapping_three" src="./js/require.js"></script>
requirejs(['three'], function (library) {
    window.THREE = library;
    // While 'three.js' may be used from here, one has however to check that the DOM and/or the full window (images, sounds, videos…) are/is loaded.  
});

Rule(s)

Example (PURE JavaScript) UV_mapping_three_js.zip 

<script src="./js/UV_mapping_three.js" type="module"></script>
/** FB_ei.js */
// 'use strict'; // No need when imported...
export var author = {value: "Franck Barbier"};
export default getAuthor; // Only one default export, i.e., import does not require braces!
function getAuthor() {
    return author.value;
};
/** Authoring_ei.js */
// 'use strict'; // No need when imported...
import {author as developer} from "./FB_ei.js"; // '.js' is mandatory!
import getAuthor from "./FB_ei.js";
export {Authoring}; // <=> {Authoring as Authoring};
var Authoring = function () {
    this._author = developer.value ? developer.value : getAuthor();
    …
};

Example (PURE JavaScript)

export class C {…} // 'export' must be synch with class declaration!

Rule(s)

Example (PURE JavaScript) Export_import.js.zip 

<script src="./js/C.js" type="module"></script>
// 'A.js' file
export let A = "A";
// 'B.js' file
import {A as proxy} from "./A.js";

export let A = proxy;
// 'C.js' file
import {A} from "./B.js";

window.alert("'A' in 'C.js': " + A); // "A" is displayed...

Rule(s)

Example

// 'index.ts' file is imported and contained code is executed:
import './persistence'; // Make database accessible and running...

Example (Node.js)

import * as HTTP from "http"; // Pure TypeScript style...
From “legacy” JavaScript to TypeScript

Rule(s)

Example (package.json and next TypeScript)

"dependencies": {…, "lodash": "^4.17.20", …},
"devDependencies": {…, "@types/lodash": "^4.14.168", …},
 import {pick} from "lodash";

Rule(s)

import * as THREE from "../three.js-r115/src/Three" // Look for 'Three.ts' or 'Three.tsx' or 'Three.d.ts'...

Rule(s)

Example

declare const dat; // Type is 'any'...
console.assert(typeof dat !== "undefined", "Problem: it won't work because 'dat.gui.min.js' library has not been loaded...");

Rule(s)

Example Covid-19_three_js.ts.zip 

// @ts-ignore (no TypeScript support for 'THREE.GLTFLoader') -> compilation error disappears!
(new THREE.GLTFLoader()).load('./models/Coronavirus-sars-co-v2.gltf', this._post_process_Covid_19.bind(this, ready)); // External lib.

Rule(s)

Example (package.json)

"typings": "dist/API.d.ts",
Packaging

Rule(s)

TypeScript favors modules by means of import and export, but namespaces may increase the way of organizing code as well (see also here…).

Example Miscellaneous.ts.zip 

// 'Namespace_Forname.ts' file
namespace Forname {
    export const my_forname = "Joseph";
}
namespace Nickname {
    export const my_nickname = "Jojo";
}
// 'Namespace_Surname.ts' file
/// <reference path="./Namespace_Forname.ts" /> // 'Nickname' namespace is referenced...
namespace Surname {
    // 'export' required to access namespace's properties in 'window.alert':
    export const my_surname = "Barbier--Darnal";
}
namespace Nickname { // This namespace crosses 2 files...
    // 'export' required to access namespace's properties in 'window.alert':
    export const my_nickname_ = "Jo"; // Conflict with 'my_nickname'...
}
window.alert(Forname.my_forname + " " + Surname.my_surname + " as " + Nickname.my_nickname + " or " + Nickname.my_nickname_);

Rule(s)

Example (generated JavaScript files are loaded in sequence)

<script src="./Namespace_Forname.js"></script>
<script src="./Namespace_Surname.js"></script>

Rule(s)

export namespace SCION {
    export interface Event {
        …
    }
    export interface State {
        …
    }
    …
}
…
import {SCION} from "./SCION_CORE";
…
const state: SCION.State = …