By using
export
andimport
(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 intsconfig.json
(e.g.,"module": "CommonJS"
), TypeScript generates JavaScript code following a module system standard:"CommonJS"
,"ES6"
,"ESNext"
, or any other.
Rule(s)
- Old-fashion JavaScript style invites us to load (in sequence) source code within HTML files, starting from external libraries to homemade code. Such a method implies a lot of manual management: sequence must respect dependencies, asynchronous loading (for performance) must be explicit using
async
,defer
etc.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>
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)
- The way
export
andimport
work in TypeScript is similar to JavaScript 6.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)
- From JavaScript 6,
export
andimport
are native supports to manage modules and their dependencies (see also here…).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)
- There is a way of instrumenting transitivity.
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)
- While JavaScript
import
looks for.js
files, TypeScriptimport
looks for.ts
files!- One may choose that no entity is imported. For example,
import
includes (and thus triggers) code execution.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...
Rule(s)
- Homemade JavaScript types from libraries are uncheckable types for the TypeScript compiler. The best way of solving the problem is the installation of a TypeScript-compliant declaration of the said types (if it exists) in a given library.
Example (
package.json
and next TypeScript)"dependencies": {…, "lodash": "^4.17.20", …}, "devDependencies": {…, "@types/lodash": "^4.14.168", …},
import {pick} from "lodash";
Rule(s)
- TypeScript declaration files (
.d.ts
suffix) are reserved for creating a compilation bridge from JavaScript to TypeScript.import * as THREE from "../three.js-r115/src/Three" // Look for 'Three.ts' or 'Three.tsx' or 'Three.d.ts'...
Rule(s)
- No TypeScript-compliant declaration of homemade types imposes bypassing TypeScript type checking;
declare
keyword may help. Indeed,declare
is used to tell TypeScript that the variable has been created elsewhere.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)
- Contextual errors may be bypassed as well.
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)
- To promote homemade types as checkable types, the
"types"
(≡"typings"
) key inpackage.json
may be used for publishing these types.Example (
package.json
)"typings": "dist/API.d.ts",
Rule(s)
- Browserify, Parcel, RequireJS, or webpack are utilities that allow packaging to simplify loading. In this scope, considering the
UV_mapping_three.js
file as the main (program) file of a simple Web application. This application reuses the three.js 3D library as a dependency. Using RequireJS as packager, only therequire.js
file is loaded within HTML.- Later on,
UV_mapping_three.js
must then load what it requires, namely three.js. Note that therequire.js
,three.js
andUV_mapping_three.js
files are together stored in ajs
sub-directory of the directory in whichindex.html
is located.
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)
- Packaging relies on the
--outFile
compiler option. Differently (no packaging), “common” script loading style may be used.Example (generated JavaScript files are loaded in sequence)
<script src="./Namespace_Forname.js"></script> <script src="./Namespace_Surname.js"></script>
Rule(s)
- Access to namespaces simply occur with
export
andimport
.export namespace SCION { export interface Event { … } export interface State { … } … } … import {SCION} from "./SCION_CORE"; … const state: SCION.State = …