Thursday, November 15, 2018

TypeScript - Namespaces - multiple files

We have introduced usage of namespace with an example in our previous blog post:
https://sashankexpresstech.blogspot.com/2018/11/typescript-namespaces-introductory.html

Consider a scenario, whereby the namespace is really huge and we would like to better organize it splitting into multiple files. In such a case, TypeScript provides us a facility by which we can hold the same namespace in multiple files.

In the previous example, we were calculating the areas of circle and square and we grouped them in one namespace: myArea.

Let us now split the namespace information of myArea in to two files:

circleArea.ts
namespace myArea {
const PI = Math.PI;
export function circleArea(radius: number){
return PI*radius*radius;
}
}

squareArea.ts
namespace myArea {

export function squareArea(sideLength:number){
return sideLength*sideLength;
}
}


the code that remains in app.ts is:
console.log(myArea.circleArea(5));
console.log(myArea.squareArea(5));

Now, if we compile:

$ tsc
$ ls -l *.js
-rw-r--r-- 1 ubuntu ubuntu  84 Nov 15 15:03 app.js
-rw-r--r-- 1 ubuntu ubuntu 211 Nov 15 15:03 circleArea.js
-rw-r--r-- 1 ubuntu ubuntu 196 Nov 15 15:03 squareArea.js

Now, if we open the browser on localhost and check the console:
Uncaught ReferenceError: myArea is not defined
    at app.js:2

We have received the above error. This is because, myArea is not defined in app.js file - which is the file included in our index.html page. To solve this problem there are two techniques:

Technique 01:
First technique involves, including all the JavaScript files inside the index.html file. We will include them in the body of our index.html file as follows:

<body>
<script src="./circleArea.js"></script>
<script src="./squareArea.js"></script>
<script src="./app.js"></script>
</body>

Please note that the order of the JavaScript file placement matters. This is because, the definitions of the namespace should come before its usage. Hence, we have placed the app.js file at the bottom.

Now, if we check the console output:
78.53981633974483
25


Technique 02:
We also have another technique in which we can combine the multiple JavaScript files into a single file using the --outFile compiler option provided with tsc. Let us use this technique as mentioned in the link:
https://www.typescriptlang.org/docs/handbook/namespaces.html#splitting-across-files

For this let us first edit our index.html file to include only the app.js file:
<body>
<script src="./app.js"></script>
</body>

Now, we will combine the TypeScript files to a single JavaScript file using the --outFile compiler option:

$ tsc --outFile app.js circleArea.ts squareArea.ts app.ts 

This will combine the 3 .ts files into a single JavaScript file:

$ ls -l *.js
-rw-r--r-- 1 ubuntu ubuntu 449 Nov 15 15:36 app.js

Now, let us start the web server:
$ python -m SimpleHTTPServer 3000
Serving HTTP on 0.0.0.0 port 3000 ...
127.0.0.1 - - [15/Nov/2018 15:44:24] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [15/Nov/2018 15:44:24] "GET /app.js HTTP/1.1" 200 -

Check the console in the browser on localhost:3000. The console output is:

78.53981633974483
25

This covers the techniques for splitting a namespace into multiple files and then using them.


Reference:

TypeScript - Namespaces - Introductory Example

Consider the following code snippet which includes functions to calculate the area of:

  • Circle
  • Square

app.ts:  -- does not include namespace
function circleArea(radius: number){
return Math.PI*radius*radius;
}

function squareArea(sideLength:number){
return sideLength*sideLength;
}

console.log(circleArea(5));
console.log(squareArea(5));

Now, when we write code like this. There are too many functions in the global scope. There are scenarios where we would like to group related functions. For example, in this scenario both these functions are calculating the area. Hence, we can combine them both into a single module. This facility provided by TypeScript to group similar code stuff is namespace.

Consider the following code snippet - which just the above code rewritten:

app.ts - includes namespace
namespace myArea {
const PI = Math.PI;
export function circleArea(radius: number){
return PI*radius*radius;
}
export function squareArea(sideLength:number){
return sideLength*sideLength;
}
}
console.log(myArea.circleArea(5));
console.log(myArea.squareArea(5));

In this, we are grouping the functions into a bigger umbrella and terming it as myArea namespace. Please note that the individual functions and variables need to be exported - so that we can use it outside the namespace. In the above code snippet, exported properties are:

##
object-type
object-name

1 variable
PI
not exported
2 function
circleArea
exported
3 function squareArea
exported



Below is console output:

78.53981633974483
25


Reference:

TypeScript - Namespaces and modules - Introduction

Manytimes, our JavaScript project grows very big, such that it becomes difficult to manage it. To manage it, we need to split it into multiple files and group related stuffs. This is called modularization. TypeScript offers us two concepts to help us with manage our project:

  1. Namespaces
  2. Modules

Reference:

Wednesday, November 14, 2018

TypeScript - Classes - Singleton pattern - read-only variables

In our previous blogpost, we saw the usage of private constructors:
https://sashankexpresstech.blogspot.com/2018/11/typescript-classes-singleton-pattern.html

To make a variable readonly, we assign the modifier readonly before it. By this the variable can be only read externally. But it cannot be assigned a value to. Consider the following example:

// Demo - readonly variables
class mySingleton {
private static instance: mySingleton;
public readonly name:string;

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

static getInstance() {
if (!mySingleton.instance) {
mySingleton.instance = new mySingleton("The Singleton Input");
}

return mySingleton.instance;
}
}

// Only One instance
let mySingletonInstance = mySingleton.getInstance();
console.log(mySingletonInstance.name);


In this example, we have assigned the readonly modifier to the variable name. Hence, we can only read the value in this variable. If we try to change the value in this variable, then we will receive a TypeScript error:

[ts] Cannot assign to 'name' because it is a constant or a read-only property.


Reference:

TypeScript - Classes - Singleton pattern and private constructors

Singleton Pattern means that you should be able to able to create only one instance of the class.  Consider the below example in which we create a SIngleton class.

// Demo - private constructors - Singleton class
class mySingleton {
private static instance: mySingleton;

private constructor(public name:string) {

}

static getInstance() {
if (!mySingleton.instance) {
mySingleton.instance = new mySingleton("The Singleton Input");
}

return mySingleton.instance;
}
}

// Only One instance
let mySingletonInstance = mySingleton.getInstance();

In this example, we ensure that it is a singleton class by:

  • making the constructor private - hence, the instance cannot be created outside the class
  • Since, the instance of the class is created within the class itself. We can place a check within the class - for creating the Singleton instance only when it is not already created.

Reference:

TypeScript - Classes - abstract classes

Abstract classes are classes which cannot be instantiated. They serve as base class from which other classes may be derived.

Consider that we want to create an abstract class for Fighter Planes:

// Abstract Classes
abstract class FighterPlanes {
manufacturerName: string = "Dassault Aviation";
budget: number = 30000;

abstract changeName(name:string) : void;
calcBudget(){
return this.budget *2;
}
}

Now, if we want to extend this class to a specific plane. The above abstract class will be a default template for all the future Fighter Planes.

class B2Spirit extends FighterPlanes {
changeName(name:string): void {
this.manufacturerName = name;
}
}

Let us instantiate this child class and save the file.

let newProject = new B2Spirit ();
console.log(newProject);
console.log(newProject.changeName("Northrop Grumman"));
console.log(newProject);


Compiling the project:

$ tsc
$

Start the Local Server:

$ python -m SimpleHTTPServer 3000
$

Check the console in the Web Browser:

B2Spirit {manufacturerName: "Dassault Aviation", budget: 30000}
city-App.ts:196 undefined
city-App.ts:197 B2Spirit {manufacturerName: "Northrop Grumman", budget: 30000}


Reference:

TypeScript - Classes - static properties and methods

When we create a class, we cannot use its properties and methods without instantiating the class.

// Static Properties and Methods
class miscItems {
E: number = 2.718;
calcMultipleE(inputMultiple:number) : number{
return this.E * inputMultiple;
}
}

But, TypeScript provides a facility to access the methods and properties without instantiating it by using the static keyword. Observe how we convert the above class to be able to hold static properties and methods and then access it directly. Consider the below rewritten code:

// Static Properties and Methods
class miscItems {
static E: number = 2.718;
static calcMultipleE(inputMultiple:number) : number{
return this.E * inputMultiple;
}
}

console.log(2*miscItems.E);
console.log(miscItems.calcMultipleE(8));

Let us now, compile the code

$ tsc
$

check the console output:

5.436
21.744

We are able to access static properties and methods  defined in a class without instantiating it.

Reference: