Modules helps in writing clean code like seperating modules for dataacces, UI and security. Each modules has a separate role of its own
like httpModule, routing module. Writing Modules in TS would create IIFE(Immediately Invoked Function Expression) in javascript file

module dataService{

}

So what is difference between class and module. Both are same except one. Classes are created in Global namespace.
However module can be either global or local.

class dataService{

}

Now lets wrap class with in module which is nothing more than namespace

module Shapes{
  export class Rectangle{

  } 

  export class Square{

  } 

  export class Triangle{

  } 
}

var objShapes:any = new Shapes.Square;

Simple Program for Logging Message using Module and Interface

interface ILoggerUtils {
    print(): void;
}

var LogLevel = {
    info: 1,
    Warn: 2,
    Error:3
}

module LogUtils {
    export class LoggerAtError implements ILoggerUtils {
        
    print(): void {
        console.log("Log Message during Error");
    }
}

export class LoggerAtInfo implements ILoggerUtils {
    print(): void {
        console.log("Log Message during Info");
    }
}

export class LoggerAtWarn implements ILoggerUtils {
    print(): void {
        console.log("Log Message during Warn");
    }
  }
}

window.onload = function () {
    var objLoggerUtil: ILoggerUtils;

    var logLevel = LogLevel.info;

    switch (logLevel) {
        case LogLevel.info:
            objLoggerUtil = new LogUtils.LoggerAtInfo();
            break;
        case LogLevel.Warn:
            objLoggerUtil = new LogUtils.LoggerAtWarn();
            break;
        case LogLevel.Error:
            objLoggerUtil = new LogUtils.LoggerAtError();
            break;
    }

    objLoggerUtil.print();
}

Output

Log Message during Info

While doing we need to let know Typescript how the datatypes are defined.The definition files are available in internet and it should be added to the script folder while doing the casting

Suppose I am doing a casting HTMLElement while accessing DOMto HTMLInputElement i should add lib.d.ts which contains the definition for DOM elements.

In the below code document.getElementById(‘Name’) returns HTMLElement which is least specific compared to HTMLInputElement.

var name = <HTMLInputElement>document.getElementById('Name');
  1. Using Interface we can have blue print of list of things which needs to be implemented
interface calculateInterest {
    accountType: String,
    interest: number,
    depAmt?: number,
    calculateInt(depositAmt: number) : number;
} 

var IntForSavings: calculateInterest = {
    accountType: "Savings",
    interest: 12,     
    depAmt : 0,
    calculateInt: function (depositAmt:number) {
        this.depAmt = depositAmt;
        return depositAmt * this.interest;
    }    
};

var IntForCurrent: calculateInterest = {
    accountType: "Current",
    interest: 5,           
    depAmt: 0,
    calculateInt: function (depositAmt: number) {
        this.depAmt = depositAmt;
        return depositAmt * this.interest;
    }
};

var IntForLoans: calculateInterest = {
    accountType: "Loan Account",
    interest: 8,
    depAmt: 0,
    calculateInt: function (depositAmt: number) {
        this.depAmt = depositAmt;
        return depositAmt * this.interest;
    }
};

console.log(IntForSavings.accountType + ' yields ' + IntForSavings.calculateInt(12000) + ' for cash amount of ' + IntForSavings.depAmt);
console.log(IntForCurrent.accountType + ' yields ' + IntForCurrent.calculateInt(6000) + ' for cash amount of ' + IntForCurrent.depAmt);
console.log(IntForLoans.accountType + ' yields ' + IntForLoans.calculateInt(3000) + ' for cash amount of ' + IntForLoans.depAmt);

Output

Savings yields 144000 for cash amount of 12000
Current yields 30000 for cash amount of 6000
Loan Account yields 24000 for cash amount of 3000

Classes extending Interface
Accounts.ts

interface Accounts {
    accountType?: string;
    calculateInterest(accountType: string): number;
}

class SavingsAcc implements Accounts {
   
    minimumBalance: number = 10000;
    accountType: string = 'Savings';    

    calculateInterest(accountType: string): number{
        return 5;
    }
}

class CurrentAcc implements Accounts {
    minimumBalance: number;
    accountType: string = 'Current';
    calculateInterest(accountType: string): number {
        return 5;
    }
}

class LoanAcc implements Accounts {
    accountType: string = 'Loan';
    calculateInterest(accountType: string): number {
        return 12;
    }
}

class Customer {
    private _accountType: Accounts;          

    constructor(customerId: number, AccountType : Accounts) {
        this._accountType = AccountType;
    }

    public get accountType(): Accounts {
        return this._accountType;
    }
    public set accountType(value: Accounts) {
        this._accountType = value;
    }
}

window.onload = function () {
    var objCustomer: Customer = new Customer(1001, new LoanAcc());    
    console.log(objCustomer.accountType.accountType + ' Account with interest rate of ' + objCustomer.accountType.calculateInterest('Loan'));


    var objCustomer: Customer = new Customer(1001, new SavingsAcc());
    console.log(objCustomer.accountType.accountType + ' Account with interest rate of ' + objCustomer.accountType.calculateInterest('Savings'));
}

Output

Loan Account with interest of 12
Savings Account with interest of 5

Accessing property of class extending Interface
We have the same code of Accounts.ts with slight modification on window.load. We try to access a property specific to class implementing interface.
In the below code minimumBalance is a property specific to savingsAccount which implements Accounts. In such case we need to do type case from generic interface object to specific class object
so the property specific to class is available.

window.onload = function () {
    var objCustomer: Customer = new Customer(1001, new SavingsAcc());
    var objSavingAcc: SavingsAcc = <SavingsAcc>objCustomer.accountType;
    console.log(objCustomer.accountType.accountType + ' Account with interest rate of ' + objCustomer.accountType.calculateInterest('Savings') + ' with minimum balance of ' + objSavingAcc.minimumBalance);
}

Output

Savings Account with interest rate of 5 with minimum balance of 10000

Using Interface to write clean code
One of the advantage of interface is while passing multiple arguments to constructor we can avoid the misplacement of the argument passed
like the one in code below. This is similar to ENUM in Java. The the Account class constructor we can change the arguments to interface as follows

Interfaces.ts

interface IPerson {
    name: string;
    age: number;
    location: string;
}

interface IEmployee extends IPerson{
    empId: number;
}

interface ICustomer extends IPerson {
    custId: number;
    accType: string;
}

Account.ts

class Account {
    private _name: string;
    private _age: number;
    private _location: string;    
    private _custId: number;   
    private _accType: string;   

    constructor(name: string, age: number, location: string, custId: number, accType: string) {    
        this._name = name;
        this._age = age;
        this._location = location;
        this._custId = custId;
        this._accType = accType;
    }
}

Refactored Account class with constructor arguments changed to inteface

Account.ts

class Account {
    private _name: string;
    private _age: number;
    private _location: string;    
    private _custId: number;   
    private _accType: string;   

    constructor(iPerson: ICustomer) {
        this._name = iPerson.name;
        this._age = iPerson.age;
        this._location = iPerson.location;
        this._custId = iPerson.custId;
        this._accType = iPerson.accType;
    }
}

Functions using arrow function Expression

var multiply = function (num: number) {
        return num * num;
}

The same above function could be written using arrow key expression as below

var multiply = (num1: number, num2: number) => return num1 * num2;

//With flower braces in case of multiple statements
var multiply = (num1: number, num2: number) => {return num1 * num2;};

we can also do function declaration and definition in two separate lines as one below

//function declaration
var multiply: (num1: number, num2: number) => number;    

//function definition
multiply = function (num1: number, num2: number) {
  return num1 * num2;
}

//function taking object literals as arguments
var multiply: (numbs: { num1: number, num2: number }) => number;    
var numbs = { num1: 2, num2: 4 };

multiply = function (numbs) {
   return numbs.num1 * numbs.num2;
}
  1. What is difference between let and var while declaring variable?
    var is Function Scoped and let is block scoped
    Using var

    var foo = 123;
    if (true) {
        var foo = 456;
    }
    
    console.log(foo); // 456
    

    Using let

    let foo = 123;
    if (true) {
        let foo = 456;
    
    }
    console.log(foo); // 123
    
  2. What would be the value of the below variables?
     
     //Value is Undefined
     var foo:string;
     
     //You can explicitly define value as undefined 
     var age = undefined;
    
     //any is a valid value which is default type until the variable assumes some data type by type inference
     var location:any;
    
     //undefined and null could be assigned to any of the datatype
     var pincode:any=undefined;
     var state:any=null;
    
  3. Why the below is not possible in interface?
    I am having a interface and class like one below which results in compile time exception

    interface test1 {
    }
    
    class test2 implements test1
    {
        public foo;
    }
    
    let test: test1 = new test2();
    
    test.foo = 'test';
    

    The reason for the compilation error is when you reference a variable with specific interface in TypeScript, you can only use the properties and methods declared in the interface of the variable
    You are assigning test1 as a type of test variable, test1 interface doesn’t have foo property in it. so that’s why you are getting this error. If you change the type to let test: test2: new test2();. it won’t throw any error like one below

    let test: test2 = new test2();
    test.foo = 'test';
    

    There are two workaround for this. One is not to define the type while initializing variable like one below

    interface test1 { }
    class test2 implements test1{
        public foo;
    }
    let test = new test2();
    test.foo = 'test';
    

    Other is to use any while initializing variable

    interface test1 { }
    class test2 implements test1{
        public foo;
    }
    let test: test1 | any = new test2();
    test.foo = 'test';
    

Type Script Command Line

//Install Typescript
>>npm install -g typescript

//Check version of Type Script
>>tsc -v

//Compile Typescript Code
//this would generate javascript file test.js
>>tsc test.ts

//Running js file
>>node test.js

Data Types in Typescript
Typescript allows to declare variable static(optional).If you use static typing then IDE will allow for type safety at compile time.

//Declaring String
let Name: String = "Mugil"; 

//Declaring Number
let Age: number = 25;

//Declaring Boolean
let Gender: boolean = true;

//Declaring Any datatype
let Street: any = 1 (or) "First" (or) true;

var is Function Scoped and let is block scoped
Using var

var foo = 123;
if (true) {
    var foo = 456;
}

console.log(foo); // 456

Using let

let foo = 123;
if (true) {
    let foo = 456;

}
console.log(foo); // 123
//Determined by Type Inference
var firstName = 'Mugil';
var age = 33;

//Determined by Annotation
var LastName: string = 'vannan';

//Not yet Determined 
var Location;

//Not yet Determined 
var Location;

var previousExp = 6 ;

//If you add a number and string it would be string irrespective of order
var totalExp = previousExp + "five";

//result in error
var Exp: number = previousExp + "five";

console.log("Total Exp - " + totalExp)

Interface

interface Person{
    name: String,
    age: number,
    pincode: any 
}

var objPerson:Person = {name: "Mugil", age:33, pincode:600018}

console.log(objPerson.pincode);

Class

class Person{
    private name: string;
    
    constructor(pname: string){
        this.name=pname;
    }    

    displayPerson(): void{
        console.log(this.name);
    }
}

var objPerson = new Person('Piggy');
objPerson.displayPerson();

Importing Namespaces and Modules

  1. Namespace are not widely used for development rather they are used internally. Modules are widely used for development
  2. In namespace you want to use would be imported using reference tag as in ArithmeticTester.ts, the one below. (Output is throwing error)
  3. When using modules the function would be directly added in module ts file as in Arithmetic.ts and referred using import in ArithmeticTester.ts
  4. Modules would be frequently used, the format would be import {FUNCTION_NAME} from ‘MODULENAME’

Namespace Example
Arithmetic.ts

namespace Arithmetic{
    export function Add(pNum1: number, pNum2: number){
        return pNum1+pNum2;
    }
}

ArithmeticTester.ts

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

let Sum = Arithmetic.Add(5,6);
console.log(Sum);

Modules Example
Arithmetic.ts

export function Add(pNum1: number, pNum2: number){
    return pNum1+pNum2;
}

ArithmeticTester.ts

import {Add} from './Arithmetic'

let Sum = Add(5,6);
console.log(Sum);

Output

11

Functions Example

  1. Arguments to function is optional. You can either set default value incase you are not sure about argument passed like in Add function
  2. You are still allowed to not pass any argument using ? in such case you would end up with different out put at runtime. NAN incase of number or undefined incase of string
  3. return type of function is not mandatory and its optional as in displayName function

Arithmetic.ts

//pNum2 would be considered as 0 incase only one argument is passed
function Add(pNum1: number, pNum2: number=0){
    return pNum1+pNum2;
}

function displayName(firstName: string, lastName? : string) : void{
    console.log("Her name is " + firstName + " "+ lastName); 
}
console.log(Add(5, 8));
console.log(Add(5));
displayName("Piggy");

Output

13
5
Her name is Piggy undefined

How to ensure type safety of arguments while using function
While defining function you may want to ensure the argument type passed.In such case you should declare the argument type the function accepts as one below.

In the below code you could see display name with two parameters(firstName and lastName). TypeSafety of second parameter is ensured by making it as string whereas first one could
be of anytype. If you try to pass something other than string as argument to second parameter then compiler would complain for error.

class SampleScript {
    displayName: (firstName, lastName: string) => void = function(firstName, lastName) {
        console.log("My Name is " + firstName + ' ' + lastName);
    }
}

window.onload = function () {
    var objSampleScript = new SampleScript();
    objSampleScript.displayName(101,'Vannan');
}

Output

My Name is 101 Vannan

Object Types
Object types could be function, module, class, interface and literal literals

Object Literals

 var square={h:10, width:10}
 var rectangle:Object ={h:10, width:20}

 //delcaring triangle as object literal
 var triangle:{};
 triangle={side1:10, side2:10, side3:10};

Functions as Object

var multiply = function (num: number) {
        return num * num;
};

//declaration of divide function object
var divide: Function;

divide = function (num1: number, num2: number) {
   return num1 / num2;
};

Object with variable and function

 var rectangle = {
        height:10,
        width:20,
        calculateArea: function() {
            return this.height* this.width;
        }
    };

    console.log(rectangle.calculateArea());
   var experience = {        
        sendExp: function (exp?: number) {
            if (exp < 3)
                return 'Beginner';
            else if (exp > 3 && exp < 6)
                return 'Intermediate';
            else
                return 'Fresher'; 

        }
    };

    console.log(experience.sendExp(5));
    console.log(experience.sendExp());

Output

Intermediate
Fresher

Function taking Object as parameter

var experience = {
        sendExp: function (job: { skill: String, exp?: number}) {
            if (job.exp < 3)
                return 'Beginner in ' + job.skill;
            else if (job.exp > 3 && job.exp < 6)
                return 'Intermediate in ' + job.skill;
            else
                return 'Fresher'; 

        }
    };

    console.log(experience.sendExp({ skill: 'Java' }));
    console.log(experience.sendExp({ skill: 'Java', exp: 5 }));

Output

Fresher
Intermediate in Java