Complete series source code can be downloaded from GitHub.
Introduction
My dear Angular lovers, I believe you have enjoyed your journey to Station 2 so far.
I 100% guarantee that now you have the basic idea behind node, npm, and have an excellent notion behind ES2015, aka ES6.
Are the words, station one and station 2 confusing you? It means that you are not following this series from the beginning.
This article is part of a series called “Journey to Angular Development”. We imagine this series as a train journey. Every time we reach a new station, we become competent in something.
Right now, we are in Station 2. Let’s start our journey to Station 3, and when you reach there, I assure you that you get well aware of TypeScript. You will understand why you need TypeScipt and how it is essential.
Complete series (Index)
— — — — — — — — — — — — — — — — — — — — — — — — —
https://www.justcompile.com/
https://www.amazon.in/Journey-Angular-Development-Sukesh-Marla/dp/9391030149
— — — — — — — — — — — — — — — — — — — — — — — — —
What is TypeScript? And Why?
We already had a quick discussion about it in the very first article. Let’s do it again.
- It is a programing language that has its compiler. On compilation, it creates JavaScript code.
- Perfect terminology should be Transpiler, not compiler, as it is creating one language from another language. We will use both the terminology throughout the series as “compiling” is the most popular word in the community, and “transpiling” is actual terminology. Both mean the same with regards to TypeScript.
- Instead of writing JavaScript, we can think of writing code in TypeScript because TypeScript makes the life of a developer life very easy. How? That’s what we are going to learning in this article.
Let’s explore the features of TypeScript.
Type-Safe and compiled environment
One of the essential advantages we get from TypeScript. It provides us a compiled environment. Let’s do a couple of demos to understand the same.
I believe you have already installed TypeScript at the global level using “npm.” If no, please do it using the following command.
npm install typescript -g
Now create a new TypeScript file “comp_env.ts” and put the following contents.
Demo 1 – Type Safety
var myName="Sukesh";
myName=2.0; //invalid code – It will throw compile error.
Compile(transpile) using the “tsc” command.
As you can see, after compilation, I am getting an error. As “myName” is string assigning number to it is not permittable. If you are wondering how “myName” becomes a string, then it’s because of a concept called “Type inference.” “Type inference” set the datatype to a variable based on the first assignment. In our case, the first assigned value was “sukesh” hence it is a string.
If needed, we can assign data types explicitly.
//Demo 2
var myName:string="Sukesh";
myName=2.0; //invalid code – It will throw compile error.
Let’s not discuss every data type in TypeScript one by one. It will be auto explored once we start with Angular Demo.
But there is one data type worth to discuss “any.” Declaring a variable with “any” datatype makes it a dynamic type variable, and it becomes open to any value all the time.
//Demo 3
var myName:any="Sukesh";
myName=2.0; //valid code – It will not throw any compile error.
Although It’s not recommended to use, it exists to support backward compatibility. Old JavaScript code, which is written without type-safety into consideration, can be migrated by setting variable type to “any.”
Demo 2 - Functions
Let’s create a new function as follows.
function myFunction(x:number,y:number):string{
var result=x+y;
}
In the above function, we are expecting two parameters of type “number,” and function signature says we will return “string,” but we are not returning anything. Let’s see what will happen to the compilation.
Let’s change the function to the following.
function myFunction(x:number,y:number):string{
return (x+y).toString();
}
Now, lets invoke the function passing wrong type of parameters.
myFunction("a",123);
Let’s compile and check the output.
These two demos are more than enough to prove the compiled environment in TypeScript.
This feature will make the life of all those developers amazingly easy who have extreme experience with static languages and now going to start extensively in JavaScript world.
Before we wrap up this compiled world explanation, there is one thing worth discussing. What happens when the compilation fails?
First, let’s try with proper code.
As you can see on a successful compilation, a JavaScript file got created.
Now, let’s try with an invalid code.
Is it surprising? When an invalid code is compiled, we will get the error in the console, but the JavaScript file will get generated.
On both success and failed compilation, the JavaScript file gets created by TypeScript.
Well, though it seems terrible, it is the default behavior, and it can be turned off by using a flag, “noEmitOnError.”
tsc comp_env.ts --noEmitOnError
The only reason I can think of for such purpose is maybe “backward compatibility.” Old legacy JavaScript code can be migrated to TypeScript without any change though it does not look a clean solution, it’s one of the ways to achieve it without much effort.
Now Let’s look at some more excellent features of TypeScript.
Latest features of JavaScript
You will find all those features in TypeScript, which you must have seen in JavaScript, including the newest JavaScript features. You can use all those features without any trouble in TypeScript. No difference in syntax.
A curiosity of one of my clients
I am willing to share a genuinely lovely conversation I had with one of my clients during my consulting work.
My client asked – “I don’t want type-safe and compiled environment. We have been using JavaScript for such a long time. We are very much used to with its dynamic behavior, and we are happy with it. Why shouldn’t I go with ES6 instead of TypeScript in such a case?”.
Well, it was a very sensible statement. Here is what I answered.
“You have a very valid question. Just tell me, can you guarantee that ES6 features will work in your client browser. You cannot guarantee it. It may or it may not. With TypeScript, you can guarantee that every feature will work in all browsers. As of now, TypeScript, by default, generates ES5 code on compilation/transpilation. It will generate the logic on behalf of you to make sure your output won’t impact. Let me explain you with the help one simple demo.”
I simply open a file from my laptop with the following content and asked him what it is?
let a=10;
console.log(a
if(true){
let a=9;
console.log(a);
}
console.log(a);
He quickly replied, “it’s a JavaScript code using ES6, let keyword”. I replied with a smile, “It’s a TypeScript code. Check the extension of the file.”
I continued, “TypeScript inherits its syntaxes from JavaScript. Everything you write in JavaScript can be written in TypeScript”.
Then, I compiled(transpiled) the TypeScript file as follows.
tsc Var_Dec.ts
Then, I open the generated JavaScript file and compared both.
I said, “It converted let to var as let is ES6 keyword but also renamed the variable inside if block which made sure that output will not get impacted. On top of that, you can guarantee that it will work on all the browsers as its purely ES5 code.”.
I continued, “TypeScript compiler will take care of new ES6 features. Whenever needed, it generates custom logic and makes sure output remains unaffected.”
He got impressed, but he is a client. He countered with another question. He said, “It sounds good to me, but what if once ES6 becomes completely compatible across all browsers? What will be the scenario by then?”
He is smart but me, either. 😉
Find my answer
“We have the second advantage of using Typescript over JavaScript. TypeScript always stays ahead of the JavaScript version. End of the day, it is one of the Microsoft products. By the time all browsers become compatible with ES6, TypeScript starts supporting features in the next version of JavaScript.”
I continued, “Plus, the third advantage is, here you will get the provision to change the target of JavaScript to be generated. As of now, TypeScript gets transpile to ES5, but by just setting one flag, we can configure it to generate ES6. So, when ES6 becomes completely compatible, we will set it to ES6 and so no extra custom logic and hence reduced file size.”
tsc Var_Dec.ts --target ES6
I ended my conversation with, “To convince you about TypeScript, let me tell you one last advantage. TypeScript will provide you some features which are not even available in ES6. I think these four reasons are more than enough to make you feel comfortable with TypeScript over ES6.”
Communication ended there 😊.
We will not do a demo of the ES6 feature and examine the generated JavaScript code. That will be an assignment for all of you.
Interfaces
Unlike JavaScript, TypeScript does support interfaces.
Let’s do a demo and understand it.
Create a TypeScript file “interface.ts” with the following contents
interface MyInterface{
MyMethod(x:string,y:number):string;
MyMethod2():number;
}
Let’s compile the above file and see what output is generated.
It’s empty.
If you are from an object-oriented programming background, then you may recollect the definition of the interface as “Its a contract everybody must follow.”
JavaScript is a dynamic language, and no contract needs to be followed. This feature is for TypeScript programmers. Let’s use it in some code, and then let’s see how JavaSCript got generated.
Create a new function “myFunction” as follows and then compile it.
function myFunction(type1:MyInterface,type2:MyInterface){
let a=type1.MyMethod("A",12);
let b=type1.MyMethod2();
let c=type2.MyMethod("B",12);
let d=type2.MyMethod2();
}
When you are using TypeScript, don’t worry much about what is getting generated. Just try to understand the development time benefit you get because of that.
For instance, let’s create a class “Customer,” which won’t implement “MyInterface,” then let’s pass an instance of it to “myFunction,” and finally, let’s compile and let’s see what happens.
interface MyInterface{
MyMethod(x:string,y:number):string;
MyMethod2():number;
}
function myFunction(type1:MyInterface,type2:MyInterface){
let a=type1.MyMethod("A",12);
let b=type1.MyMethod2();
let c=type2.MyMethod("B",12);
let d=type2.MyMethod2();
}
class Customer{
}
let c=new Customer();
myFunction(c,c);
As you can see, it is enforcing you to pass instance which is following the contract and contract says, it must contain a definition for method “MyMethod” and “MyMethod2”.
You will see interfaces and all other features real-time in action in Angular demos.
Generics
Generic is a programming methodology where we write our code in a way it works for multiple data types. We won’t explicitly specify the data type at the time of developing functionality. Instead, we specify datatype at the time of using it.
Let’s do a demo and understand the same.
I believe, as a programmer, you know what an array is. It’s a collection of elements of similar types.
But in JavaScript, the concept is a little different. In JavaScript, an array can hold items of different data types at the same time.
As you know, TypeScript is a typed language, and we have a generic class called “Array” here. It will let us create a collection holding items of similar data types.
Look at the following code.
let myArray:Array<number>=new Array<number>();
The above code will create an array of numbers called “myArray.”
Let’s try to add some items to it.
myArray.push(1); // valid code
myArray.push(1); // valid code
myArray.push("Sukesh"); // invalid code - compile error
Now, let's use the same “Array” class for creating an array of string values.
let myStrings:Array<string>=new Array<string>();
myStrings.push("Sukesh"); // valid code
myStrings.push("Marla"); // valid code
myStrings.push(1); // invalid code - compile error
It is generic programming, and it is giving us two advantages.
- “Array” class can be used for multiple data types. It’s not bound to one specific datatype.
- It is type-safe. It can work with various data types, but it doesn’t make it type-unsafe.
Now that you do TypeScript have support for Generics, let’s create our generic custom function to take our understanding to the next level.
Look at the following code.
function IsEqual(x:number,y:number):boolean{
if(x==y){
return true;
}
else{
return false;
}
}
The above function is bound to only numbers. We cannot use the same for strings.
Change the above code to the following.
function IsEqual(x,y):boolean{
if(x==y){
return true;
}
else{
return false;
}
}
console.log(IsEqual(1,2));
console.log(IsEqual("A","B"));
let compile it using “tsc.”
It seems it’s working. But is it?
Let’s test the code with one more possibility.
function IsEqual(x,y):boolean{
if(x==y){
return true;
}
else{
return false;
}
}
console.log(IsEqual(1,2));
console.log(IsEqual("A","B"));
console.log(IsEqual("A",2));
We haven’t changed anything. We only added one more function call but this time we passed one string and one number. Let’s see if it compiles properly.
Yes, it’s working. Is it an expected output? The answer is No.
By removing datatypes from the function parameter signature, we simply made it “any” type, and hence it can except the value of all data types.
As per our expectation, both parameters have to be of the same data type.
It can be achieved by making it a generic code.
function IsEqual<T>(x:T,y:T):boolean{
if(x==y){
return true;
}
else{
return false;
}
}
console.log(IsEqual<number>(1,2));// valid code
console.log(IsEqual<string>("A","B"));// valid code
console.log(IsEqual<number>("A","B"));// invalid code - compile error
console.log(IsEqual<number>(1,"B"));// invalid code - compile error
Compile it, and hence you will see a similar result.
That’s it for generic.
Enums
Enums are named constants. Don’t worry if you are not clear about it.
Many times in programming, we come across a situation where we have to declare constants. For instance, look at the following code.
//Constants - May be declared in some different file
const AddMode:string="Add";
const EditMode:string="Edit";
let currentMode=GetCurrenMode();
if(currentMode==AddMode){
//Do Save operation
}
else if(currentMode==EditMode){
//Do Update Operatopm
}
Now, let’s define “GetCurrentMode” function.
function GetCurrenMode():string{
//Some logic
return "Veg Burger";
}
Now, if you compile the above TypeScript code, it will compile without any error.
I think you are smart enough to realize the problem in the above code. Value “Veg Burger” is not valid for the modes, but there is no way to identify it at compile time.
It can be solved using enums.
Let’s re-write the same code using enums.
const enum Mode{
AddMode="Add",
EditMode="Edit"
}
let currentMode:Mode=GetCurrenMode();
if(currentMode==Mode.AddMode){
//Do Save operation
}
else if(currentMode==Mode.EditMode){
//Do Update Operatopm
}
function GetCurrenMode():Mode{
return Mode.VegBurger;
}
Now, let’s compile it.
Enums make working constant easier and make code more readable.
Modules
Working with modules is super easy if you know ES6 modules.
We already discussed it in detail in this article.
Let’s do a quick demo here.
Create an independent folder (to avoid confusion) called “Module-demo” and create two TypeScript files “simple.ts” and “reusable.ts” as follows.
//reusable.ts
export function getString():string{
return getString2();
}
function getString2():string{
return "Just Compile";
}
//simple.ts
import { getString as myFunction } from "./reusable";
console.log(myFunction());
Now compile “simple.ts” using the “tsc” command.
Please note, we have not compiled “reusable.ts” explicitly. It got compiled automatically because “simple.ts” is using it.
Let’s look at the generated code. Lets open “simple.ts.”
"use strict";
exports.__esModule = true;
//simple.ts
var reusable_1 = require("./reusable");
console.log(reusable_1.getString());
What you see in the above code is the “CommonJS” format. If you remember, in our discussion on “Module Formatters,” we said there are a lot of “Module Formatters,” and we did our demo with AMD. TypeScript, by default, generates the “CommonJS” format.
If we want, we can instruct the TypeScript compiler to generate the “AMD” format code using the “--module” flag.
Let’s check what code we got.
define(["require", "exports", "./reusable"],
function (require, exports, reusable_1) {
"use strict";
exports.__esModule = true;
console.log(reusable_1.getString());
});
Does it seem familiar code to you? It is an AMD code.
Using existing JavaScript files in TypeScript
In my 12+ years of experience, I worked in various roles. I worked as a developer, architect, freelancer, consultant, trainer, author, and finally, as a director of an organization. Still, I never saw a web project where no external JavaScript files are used.
If we are planning to write code in TypeScript, then what about the external JavaScript files (which are not compiled from TypeScript)? How to use them.?
Let’s consider “jQuery” for the demonstration purpose.
Create a TypeScript file “simple.ts” as follows.
$(document).ready(function() {
$('#myElement').text("Just Compile");
}
);
Those who are not able to understand the above code for them, it’s a “jQuery” code. Don’t get into the depth of it for now. Just remember that it will change the inner text of the HTML element, having id “myElement.”
Let’s compile the code using the “tsc” command.
Unfortunately, “$” is not a known keyword for TypeScript. Hence compilation failed.
The solution for this is “Type Definition files.”
Type Definition files
Type Definition files are TypeScript files with “d.ts” as an extension. It will contain only declarations of all the artifacts of a JavaScript library. For instance, type definition file of “jQuery” will contain declaration of all the function which are available inside “jQuery.”
Once we have the type definition files, we can import from those type definition files.
The good news is, Type definition files are available for almost all the major reusable community libraries. So, let’s download the type definition file of “jQuery.”
npm install @types/jquery
After executing the above command, you will notice the “@types” folder gets created inside the “node_modules” folder.
Now change your TypeScript code to the following code.
import $ from “jquery”;
$(document).ready(function() {
$('#myElement').text("Just Compile");
}
);
As you can see, the compilation is successful. Now TypeScript compiler recognizes the “$” function.
Now let’s try to execute the above file by including it in the HTML file. We are going to use “webpack-dev-server” for this purpose. We discussed “webpack-dev-server” in the last article.
Create a new HTML file “index.html” as follows.
<html>
<head>
<title>External library demo</title>
<script src = "dist/main.js"></script>
</head>
<body>
<h1>Welcome to, <span id="myElement">Train IT Solutions</span></h1>
</body>
</html>
Let’s execute “webpack-dev-server” using the following command.
webpack-dev-server --entry ./simple.js --output-filename ./dist/main.js
Let’s check the output.
Let’s understand the reason for this error.
We downloaded “jQuery” type Definition files, but we have not downloaded “jQuery” library files that is “jquery.js.”
Type definition files only made TypeScript aware of “jQuery” so that it can be compiled. “jQuery” library needs to be downloaded explicitly and include it in your HTML file to make it work.
Let “webpack-dev-server” keep running in the background. Open another command prompt and download “jQuery” using “npm.”
Now, include it in the HTML file.
npm install jquery
Please be careful while using the “npm” command.
Include “jQuery” in HTML file.
<html>
<head>
<title>External library demo</title>
<script src="./node_modules/jquery/dist/jquery.js"></script>
<script src = "dist/main.js"></script>
</head>
<body>
<h1>Welcome to, <span id="myElement">Train IT Solutions</span></h1>
</body>
</html>
What if we don’t have type definition files?
It’s 100% possible. Type definition files are not available for every external JavaScript file.
For instance, let say we have a JavaScript file called “myLib.js” with the following code.
function getAuthorName(){
return “Sukesh Marla”;
}
Let’s say we want to use “getAuthorName” from the above JavaScript file in our TypeScript code.
Let’s create a TypeScript file “simple.ts” and directly try to use above function in the TypeScript file.
//simple.ts
alert(getAuthorName());
We can solve this problem with a logical solution. Change “simple.ts” above code as follows.
//simple.ts
var getAuthorName:any;
alert(getAuthorName());
As you can see, we can compile now.
Let’s test it in the HTML file.
Create an HTML file as follows.
<html>
<head>
<title>External library demo</title>
<script src = "dist/main.js"></script>
</head>
<body>
</body>
</html>
Let’s execute “webpack-dev-server” using the following command.
webpack-dev-server --entry ./simple.js --output-filename ./dist/main.js
Just like the last lab, we have to include “myLib.js” in the HTML file explicitly.
Let’s change the HTML file to following.
<html>
<head>
<title>External library demo</title>
<script src="myLib.js"></script>
<script src = "dist/main.js"></script>
</head>
<body>
</body>
</html>
We are still not getting the output.
To understand the reason for this, open the generated “simple.js” file.
//simple.ts
var getAuthorName;
alert(getAuthorName());
Did you notice “var getAuthorName;”?
We should somehow instruct the TypeScript compiler to skip this line while transpiling. It can be done with the “declare” keyword.
Change the “simple.ts.” to the following.
//simple.ts
declare var getAuthorName:any;
alert(getAuthorName());
Now recompile TypeScript file and examine the generated JavaScript file.
alert(getAuthorName());
As you can see, that declaration statement is skipped.
“webpack-dev-server” re-bundled automatically, and output in browser get refreshed.
TypeScript configuration
When it comes to the real-time project, we will have a lot of TypeScript files, and we cannot compile Each of them individually. We need some shortcut way to transpile all of them in one go.
On top of that, we expect a lot of settings of TypeScript to be set on the project level, not file level. For instance, we want to set a target to “es6”.
It can be done with the help of the configuration file.
Create a folder and execute the “tsc --init” command.
You will notice the “tsconfig.json” file gets generated inside the folder.
You will see a lot of options mentioned inside it.
Let’s start with one demo.
Create two TypeScript files, “one.ts” and “two.ts” with some random TypeScript code.
Now, open the command prompt and navigate to the folder and execute “tsc” without any parameter.
Can you imagine what happened?
It compiled every file in the folder. It works only if the “tsconfig.json” file exists.
Not only that, but it took settings inside “tsconfig.json” into consideration while transpiling.
Let’s quickly talk about a couple of settings.
Most of the options are self-explanatory. You can explore the time to time.
You can check https://www.typescriptlang.org/docs/handbook/compiler-options.html and read about each option in case interested. In case anything confuses you drop a comment. We will be more than happy to help.
Decorators
Decorators are one more important feature in TypeScript.
We will not do any demo for Decorator. You can see them in action once we start with Angular, but we will do a quick discussion and get an overview.
Decorator let us add some new behavior to functions, classes, properties, etc.
We share similar features in other technologies too. In Java, it is “Annotation,” In C#, they are “Attributes,” and in Python, its called “Decorators.”
Let’s not worry about Decorators much now. We will see them in action in Angular, and I promise you will like them and understand the benefit of it as well.
Conclusion
It’s time to celebrate. With the article, we will start our journey to the next level. We have finally reached a point where we can begin with Angular. Keep your excitement to the top, and see you in the following article.
I hope you have enjoyed this writing.
Stay tuned and practice. Please drop comments and share them on your social media. It helps us to stay motivated to write more such series.
You can check me out on twitter @sukeshmarla.
In case you are looking for customized mobile or web application development, exclusive technical consulting for architecting your project, or want to train your people in advanced technologies, you can visit my company Just Compile or contact SukeshMarla@Gmail.com for details.
Top comments (3)
Where can I find part 1?
Entire Series links is mentioned in post. Let me know need any helping in finding.
Fabian, You can find articles link in the same page Complete Series Section.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.