TypeScript is a superset of JavaScript that is statically typed, which means when you compile the code the compiler will already know about all the variables and their type.
For example, if in an empty JavaScript file you paste the following code,
1
2
3
if (arr.length > 0) {
print('arr is not empty')
}
no error will pop up, it is a perfectly valid JavaScript code even though arr is not defined. And because of this working with JavaScript, which is a dynamically typed language, it is easier. But, when your app scales, this may introduce strange bugs which will be hard to debug. Here comes TypeScript to your rescue. You cannot use undeclared variables in it. Want to test it? Add the line
// @ts-check
at top of your JavaScript file.
The following error will pop up.
The following Reddit post perfectly explains why you should be using TypeScript.
Now that you know what TypeScript is and how it is beneficial, let’s start by setting it up. Run the command npm i typescript -g in your terminal. It will install TypeScript globally in your system.
TypeScript does not run anywhere on its own. Rather, the compiler converts it to JavaScript which can be executed normally.
In an empty folder create two files:
index.ts
tsconfig.json
The first file is where we will write our TypeScript code and the second file will tell the compiler how we want to compile our code. Although the second file is not necessary, we will use it as it is common practice.
Paste the following code in tsconfig file.
1 2 3 4 5
{ "compilerOptions": { "target": "esnext" } }
It is telling the compiler what es version to use (here it will automatically use the latest version).
Now, following the tradition, we will first write a Hello World code. It will tell us whether our setup is correct or not. Paste the following code in the index.ts file.
console.log('Hello world');
And now run tsc index.ts command. Tsc is the compiler. A file called index.js will be created automatically and it will have the code converted to JavaScript. And your code should look like this.
Let’s modify the tsconfig file a bit and then we will dive into TypeScript. We will add the watch key which will automatically compile the code any time we save the file.
1 2 3 4 5 6
{ "compilerOptions": { "target": "esnext", "watch": true } }
If you run the command tsc then it will begin in watch mode.
We can assign the type to a variable using implicit declaration, which means that at the time of declaration, if you assign it a value then it will become of its type. So if you assign a variable the value of a number then it will remain a number forever.
1
2
let num = 23;
num = '23';
And you will get the following error.
Since num was assigned a number’s value at the beginning it cannot be made a string.
But, what if we don’t have any value at the beginning to assign to the variable? Here we can use the explicit declaration.
let num: number;
This variable num is now a number. Now look at the following code.
1
2
3
let num: number;
num = 23;
num = 'Srajan';
Line three throws the following error.
This means our type system is working fine.
Now, what if you really want a dynamic variable that can take any type? Here we will use any keyword. Although using dynamic variables is not recommended, you have the ability to do so if needed, like this.
1
2
3
let num: any;
num = 23;
num = 'Srajan';
Here, we will not get any errors.
You can also create your own custom types in the following way.
1 2 3 4
const person1 = { first: 'Jon', last: 'Doe' };
Now, let’s create a definition for this type of object, using interfaces.
1 2 3 4 5 6 7 8
interface Person { first: string, last: string } const person1: Person = { first: 'Jon', last: 'Doe' };
Here, person is the definition of our data type and person1 is an object of that data type. But, what if you want to add a few additional properties to the person object? For example, you may also want to add age property to a person1 object but do not want to make it mandatory, that is, you should be able to add age if you want to but can skip it as well. To do that you can do this.
1
2
3
4
5
6
7
8
9
10
interface Person {
first: string,
last: string,
[key: string]: any
}
const person1: Person = {
first: 'Jon',
last: 'Doe',
age: 20
};
Now you can add any string as a key, but the first and last are compulsory.
To create a function use the following syntax. Datatype declaration is not necessary, though.
1
2
3
function functionName(variableName: dataType, ...): returnType {
}
You can even use void as a return type if you want.
For example:
1
2
3
4
5
function square(a: number): number {
return a * a;
}
square(4);
We can also declare our arrays to be of a certain type, although it is not necessary. If no type is defined then any type of value can be stored. Example,
1
2
3
const nums: number[] = [];
nums.push(5);
nums.push(4);
When we know exactly what value we want to assign to our variable and we do it ourselves, this is called explicit data type. For example, in the following code, we have declared the variable to be a string.
const car:String = 'Honda';
Whereas, if we do not know what data type we should declare then we let the compiler take over. For example:
const car = 'Honda';
Here, the compiler will assign a type to the variable itself. Now if we hover over the variable the IDE will show us the type.
Surprisingly the compiler provides the type “Honda” itself, which is a lot more precise than a string.
Since JavaScript does not natively support any type annotations, whenever we compile the TypeScript code, the data types get stripped down/erased so that the code can be transformed to JavaScript code. This is why the compiler is needed. For example, paste the following code in your TypeScript file.
1
2
3
4
5
function greet(person: string, date: Date) {
console.log(`Hello {person}, today is {date.toDateString()}!`);
}
greet("Maddison", new Date());
And look at the output in the JavaScript file:
1
2
3
4
function greet(person, date) {
console.log(`Helloo {person}, today is {date.toDateString()}!`);
}
greet("Maddison", new Date());
You can see, for example, in the function arguments, the data types have been removed.
If you remove the following key from the tsconfig.json file and then compile the above-written typescript code, then you will see something weird.
"target": "esnext",
The template string that used backticks got transformed to plain string with concatenations (see below).
1
2
3
4
function greet(person, date) {
console.log("Helloo " + person + ", today is " + date.toDateString() + "!");
}
greet("Maddison", new Date());
This is called down leveling. TypeScript converts the newer version code to the older one. This is why I added the appropriate key in the tsconfig.json file.
TypeScript allows you to tell your app how strict you want your type checking to be, all of the following flags can be added/removed in the tsconfig.json file.
For example, you must remember the type ‘any’; using it defeats the TypeScript’s purpose, you can disable it using
noImplicitAny: true
Sometimes forgetting to handle null/undefined values is a big mistake. TypeScript can help you by making these checks more explicit, and we can rest assured that we certainly didn’t forget about handling null/undefined. You can do that using
stringNullChecks: true
This was the basics of TypeScript, hope you liked it.✌