Category: 09. Miscellaneous

https://cdn3d.iconscout.com/3d/premium/thumb/sticker-3d-icon-png-download-10872475.png

  • Modules

    A module is designed with the idea to organize code written in TypeScript. Modules are broadly divided into −

    • Internal Modules
    • External Modules

    Internal Module

    Internal modules came in earlier version of Typescript. This was used to logically group classes, interfaces, functions into one unit and can be exported in another module. This logical grouping is named namespace in latest version of TypeScript. So internal modules are obsolete instead we can use namespace. Internal modules are still supported, but its recommended to use namespace over internal modules.

    Internal Module Syntax (Old)

    module TutorialPoint { 
       export function add(x, y) {  
    
      console.log(x+y); 
    } }

    Namespace Syntax (New)

    namespace TutorialPoint { 
       export function add(x, y) { console.log(x + y);} 
    }
    

    JavaScript generated in both cases are same

    var TutorialPoint;(function(TutorialPoint){functionadd(x, y){console.log(x + y);} 
       TutorialPoint.add = add;})(TutorialPoint ||(TutorialPoint ={}));

    External Module

    External modules in TypeScript exists to specify and load dependencies between multiple external js files. If there is only one js file used, then external modules are not relevant. Traditionally dependency management between JavaScript files was done using browser script tags (<script></script>). But thats not extendable, as its very linear while loading modules. That means instead of loading files one after other there is no asynchronous option to load modules. When you are programming js for the server for example NodeJs you dont even have script tags.

    There are two scenarios for loading dependents js files from a single main JavaScript file.

    • Client Side – RequireJs
    • Server Side – NodeJs

    Selecting a Module Loader

    To support loading external JavaScript files, we need a module loader. This will be another js library. For browser the most common library used is RequieJS. This is an implementation of AMD (Asynchronous Module Definition) specification. Instead of loading files one after the other, AMD can load them all separately, even when they are dependent on each other.

    Defining External Module

    When defining external module in TypeScript targeting CommonJS or AMD, each file is considered as a module. So its optional to use internal module with in external module.

    If you are migrating TypeScript from AMD to CommonJs module systems, then there is no additional work needed. The only thing you need to change is just the compiler flag Unlike in JavaScript there is an overhead in migrating from CommonJs to AMD or vice versa.

    The syntax for declaring an external module is using keyword export and import.

    Syntax

    //FileName : SomeInterface.ts 
    export interface SomeInterface { 
       //code declarations 
    }
    

    To use the declared module in another file, an import keyword is used as given below. The file name is only specified no extension used.

    import someInterfaceRef = require(./SomeInterface);
    

    Example

    Lets understand this using an example.

    // IShape.ts exportinterfaceIShape{draw();}// Circle.ts import shape =require("./IShape");exportclassCircleimplementsshape.IShape {publicdraw(){console.log("Cirlce is drawn (external module)");}}// Triangle.ts import shape =require("./IShape");exportclassTriangleimplementsshape.IShape {publicdraw(){console.log("Triangle is drawn (external module)");}}// TestShape.ts import shape =require("./IShape");import circle =require("./Circle");import triangle =require("./Triangle");functiondrawAllShapes(shapeToDraw: shape.IShape){
       shapeToDraw.draw();}drawAllShapes(newcircle.Circle());drawAllShapes(newtriangle.Triangle());

    The command to compile the main TypeScript file for AMD systems is −

    tsc --module amd TestShape.ts
    

    On compiling, it will generate following JavaScript code for AMD.

    File:IShape.js

    //Generated by typescript 1.8.10define(["require","exports"],function(require, exports){});

    File:Circle.js

    //Generated by typescript 1.8.10define(["require","exports"],function(require, exports){var Circle =(function(){functionCircle(){}
    
      Circle.prototype.draw=function(){console.log("Cirlce is drawn (external module)");};return Circle;})();
    exports.Circle = Circle;});

    File:Triangle.js

    //Generated by typescript 1.8.10define(["require","exports"],function(require, exports){var Triangle =(function(){functionTriangle(){}
    
      Triangle.prototype.draw=function(){console.log("Triangle is drawn (external module)");};return Triangle;})();
    exports.Triangle = Triangle;});

    File:TestShape.js

    //Generated by typescript 1.8.10define(["require","exports","./Circle","./Triangle"],function(require, exports, circle, triangle){functiondrawAllShapes(shapeToDraw){
    
      shapeToDraw.draw();}drawAllShapes(newcircle.Circle());drawAllShapes(newtriangle.Triangle());});</code></pre>

    The command to compile the main TypeScript file for Commonjs systems is

    tsc --module commonjs TestShape.ts
    

    On compiling, it will generate following JavaScript code for Commonjs.

    File:Circle.js

    //Generated by typescript 1.8.10var Circle =(function(){functionCircle(){}
       Circle.prototype.draw=function(){console.log("Cirlce is drawn");};return Circle;})();
    
    exports.Circle = Circle;

    File:Triangle.js

    //Generated by typescript 1.8.10var Triangle =(function(){functionTriangle(){}
       Triangle.prototype.draw=function(){console.log("Triangle is drawn (external module)");};return Triangle;})();
    exports.Triangle = Triangle;

    File:TestShape.js

    //Generated by typescript 1.8.10var circle =require("./Circle");var triangle =require("./Triangle");functiondrawAllShapes(shapeToDraw){
       shapeToDraw.draw();}drawAllShapes(newcircle.Circle());drawAllShapes(newtriangle.Triangle());

    Output

    Cirlce is drawn (external module)
    Triangle is drawn (external module)
    
  • Namespaces

    A namespace is a way to logically group related code. This is inbuilt into TypeScript unlike in JavaScript where variables declarations go into a global scope and if multiple JavaScript files are used within same project there will be possibility of overwriting or misconstruing the same variables, which will lead to the global namespace pollution problem in JavaScript.

    Defining a Namespace

    A namespace definition begins with the keyword namespace followed by the namespace name as follows −

    namespace SomeNameSpaceName {exportinterfaceISomeInterfaceName{}exportclassSomeClassName{}}

    The classes or interfaces which should be accessed outside the namespace should be marked with keyword export.

    To access the class or interface in another namespace, the syntax will be namespaceName.className

    SomeNameSpaceName.SomeClassName;
    

    If the first namespace is in separate TypeScript file, then it should be referenced using triple slash reference syntax.

    /// <reference path = "SomeFileName.ts" />
    

    The following program demonstrates use of namespaces −

    FileName :IShape.ts 
    ----------namespace Drawing {exportinterfaceIShape{draw();}}  
    
    FileName :Circle.ts 
    ----------/// <reference path = "IShape.ts" /> namespace Drawing {exportclassCircleimplementsIShape{publicdraw(){console.log("Circle is drawn");}  
    
      
      FileName :Triangle.ts 
      ----------/// &lt;reference path = "IShape.ts" /&gt; namespace Drawing {exportclassTriangleimplementsIShape{publicdraw(){console.log("Triangle is drawn");}} 
         
         FileName : TestShape.ts 
         /// &lt;reference path = "IShape.ts" /&gt;   /// &lt;reference path = "Circle.ts" /&gt; /// &lt;reference path = "Triangle.ts" /&gt;  functiondrawAllShapes(shape:Drawing.IShape){ 
            shape.draw();}drawAllShapes(newDrawing.Circle());drawAllShapes(newDrawing.Triangle());}}}</code></pre>

    The above code can be compiled and executed using the following command −

    tsc --out app.js TestShape.ts  
    
    node app.js
    

    On compiling, it will generate following JavaScript code(app.js).

    //Generated by typescript 1.8.10/// <reference path = "IShape.ts" />var Drawing;(function(Drawing){var Circle =(function(){functionCircle(){}
    
      Circle.prototype.draw=function(){console.log("Cirlce is drawn");};return Circle;}());
    Drawing.Circle = Circle;})(Drawing ||(Drawing ={}));/// <reference path = "IShape.ts" />var Drawing;(function(Drawing){var Triangle =(function(){functionTriangle(){}
      Triangle.prototype.draw=function(){console.log("Triangle is drawn");};return Triangle;}());
    Drawing.Triangle = Triangle;})(Drawing ||(Drawing ={}));/// <reference path = "IShape.ts" />/// <reference path = "Circle.ts" />/// <reference path = "Triangle.ts" />functiondrawAllShapes(shape){ shape.draw();}drawAllShapes(newDrawing.Circle());drawAllShapes(newDrawing.Triangle());

    When the above code is compiled and executed, it produces the following result −

    Circle is drawn 
    Triangle is drawn
    

    Nested Namespaces

    You can define one namespace inside another namespace as follows −

    namespace namespace_name1 {exportnamespace namespace_name2 {exportclassclass_name{}}}

    You can access members of nested namespace by using the dot (.) operator as follows −

    FileName : Invoice.ts  
    namespace tutorialPoint {exportnamespace invoiceApp {exportclassInvoice{publiccalculateDiscount(price:number){return price *.40;}}}} 
    FileName: InvoiceTest.ts 
    
    /// <reference path = "Invoice.ts" />var invoice =newtutorialPoint.invoiceApp.Invoice();console.log(invoice.calculateDiscount(500));

    The above code can be compiled and executed using the following command −

    tsc --out app.js InvoiceTest.ts 
    node app.js
    

    On compiling, it will generate following JavaScript code(app.js).

    //Generated by typescript 1.8.10var tutorialPoint;(function(tutorialPoint){var invoiceApp;(function(invoiceApp){var Invoice =(function(){functionInvoice(){}
    
         Invoice.prototype.calculateDiscount=function(price){return price *.40;};return Invoice;}());
      invoiceApp.Invoice = Invoice;})(invoiceApp = tutorialPoint.invoiceApp ||(tutorialPoint.invoiceApp ={}));})(tutorialPoint ||(tutorialPoint ={}));/// &lt;reference path = "Invoice.ts" /&gt;var invoice =newtutorialPoint.invoiceApp.Invoice();console.log(invoice.calculateDiscount(500));</code></pre>

    When the above code is compiled and executed, it produces the following result −

    200
    
  • Triple-Slash Directives

    Triple-slash directives are similar to single-line comments which contain a single XML tag. They are used to provide instructions to the TypeScript compiler about processing the TypeScript file. Triple-slash directives start with three forward slashes (///) and are mainly placed at the top of the code file.

    Triple-slash directives are mostly used in TypeScript. However, they can also be used with JavaScript projects that use TypeScript.

    In TypeScript, you can use triple-slash directives for two purposes.

    Reference Directives

    Reference directives are mainly used to tell the compiler to include another TypeScript file in the compilation process. They specify the dependencies between multiple files. Furthermore, they are also used to declare dependency packages and include libraries in the TypeScript file.

    Syntax

    /// <reference path="file_path" />

    In the above syntax, we have used three forward slashes first to define the triple-slash directives. After that, we used the XML tag <reference /> and added a path attribute to it. The path attribute takes the file path as a value.

    Similarly, you can also use other XML tags with three forward slashes.

    Types of Triple-Slash Reference Directives

    Here are the most commonly used triple-slash reference directives in a JavaScript/TypeScript environment:

    • ///<reference path=”…” /> − It is used to add a reference of one TypeScript file in another file.
    • ///<reference types=”…” /> − It is used to declare a dependency on a package.
    • ///<reference lib=”…” /> − It is used to include a library file that is part of the compilation context.

    Example: Referencing File Paths

    The main purpose of the triple-slash directives is to reference other files in particular TypeScript files.

    Filename: MathFunctions.ts

    In the below code, we have defined the add() function that takes two numbers as a parameter and returns the sum of them. We also export that function using the export keyword to use it in a different file.

    // This file will be referenced in app.tsexportfunctionadd(a:number, b:number):number{return a + b;}

    Filename: app.ts

    In this file, we have imported the add() function from the mathFunctions file. We have also used the reference directive in this file to tell the file path to the compiler.

    /// <reference path="mathFunctions.ts" />import{ add }from'./mathFunctions';console.log('Addition of 10 and 20 is:',add(10,20));

    Output

    Addition of 10 and 20 is 30
    

    Example: Referencing Type Definition

    The triple-slash directives can also be used to specify the reference type definition for the external module. You can use the <reference type=”module_type” /> directive to specify the type of the module.

    App.ts

    In the code below, we have imported the fs module. Before that, we have used the triple-slash directive to specify the type of the module.

    Next, we used the readFileSync() method of the fs module to read the file content.

    /// <reference types="node" />import*as fs from'fs';const content = fs.readFileSync('sample.txt','utf8');console.log('File content:', content);

    Sample.txt

    The below file contains plain text.

    Hello, this is a sample text file.
    

    Output

    File content: Hello, this is a sample text file.
    

    Example: Including Libraries

    When you want to use a specific library during the TypeScript compilation, you can use the ///<reference lib=”lib_name” /> triple-slash directive to specify it.

    In the code below, we have used the triple-slash directive to specify the es2015.array library.

    /// <reference lib="es2015.array" /> const str =["Hello","1","World","2"];const includesTwo = str.includes("2");console.log(includesTwo);

    Output

    true
    

    Module System Directives

    Module system directives are used to specify how modules are loaded in the TypeScript file. They are used to load modules asynchronously.

    There are two types of module system directives in TypeScript:

    • ///<amd-module name=”…” />: It is used to specify the module name for loading.
    • ///<amd-dependency path=”…” />: It is used to specify the path for the dependencies of the AMD module.

    Example

    In the code below, we have used the AMD-module triple-slash directive which specifies to load the MyModule module asynchronously.

    /// <amd-module name="MyModule" />exportfunctiondisplayMessage(){return"Hello from MyModule";}

    Triple-slash directives allow developers to enhance JavaScript projects by providing advanced compilation options, module loading, and integration with various types and libraries.