TypeScript Modules


Creative Commons License
This -TypeScript Modules- tutorial is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License
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 = …