TypeScript Tutorial
TypeScript Tutorial
Introduction to TypeScript
TypeScript is a superset of JavaScript.
TypeScript builds on top of JavaScript. First, you write the TypeScript code. Then,
you compile the TypeScript code into plain JavaScript code using a TypeScript
compiler.
Once you have the plain JavaScript code, you can deploy it to any environment that
JavaScript runs.
TypeScript files use the .ts extension rather than the .js extension of JavaScript files.
TypeScript uses the JavaScript syntaxes and adds additional syntaxes for supporting
Types.
If you have a JavaScript program without any syntax errors, it is a TypeScript
program. This means that all JavaScript programs are TypeScript programs. This is
very helpful if you migrate an existing JavaScript codebase to TypeScript.
The following diagram shows the relationship between TypeScript and JavaScript:
JavaScript:
function add(x, y) {
return x + y;
}
TypeScript:
return x + y;
If you use VS Code, you can install the following extension to speed up the
development process:
Live Server – allows you to launch a development local web server with the
hot reload feature.
Install [Link]
Download the suitable [Link] version for your platform such as Windows,
macOS, or Linux.
Verify the installation by opening the Terminal on macOS and Linux or the
Command Prompt on Windows and typing the command node -v, you should
see the installed version of [Link].
To install the TypeScript compiler, you launch the Terminal on macOS or Linux and
Command Prompt on Windows and type the following command:
After the installation, you can type the following command to check the current
version of the TypeScript compiler:
tsc --v
It should return the version like this:
If you want to run TypeScript code directly on [Link] without precompiling, you can
use the tsx module.
To install the tsx module globally, run the following command from the Terminal on
macOS and Linux or Command Prompt on Windows:
Install VS Code
Execute the downloaded package or the installer file to launch the setup
wizard. The installation process is also quite straightforward.
Summary
Summary: in this section, you’ll learn how to develop the Hello World program in
TypeScript.
[Link](message);
6. Type the following command on the Terminal to compile the [Link] file:
If everything is fine, you’ll see a new file called [Link] is generated by the TypeScript
compiler:
To run the [Link] file in [Link], you use the following command:
node [Link]
If you installed the tsx module mentioned in the 2 . TypeScript Setup, you can use
just one command to run the TypeScript file directly on [Link] without precompiling
it to JavaScript:
tsx [Link]
Why TypeScript
Summary: in this section, you’ll learn why you should use TypeScript over
JavaScript to avoid the problems created by the dynamic types.
TypeScript adds a type system to help you avoid many problems with
dynamic types in JavaScript.
"Hello"
From the value, you can tell that its type is string.
let box;
box = "hello";
box = 100
The type of the box variable changes based on the value assigned to it.
To find the type of the box variable at runtime, you use the typeof operator:
let box;
[Link](typeof(box)); // undefined
box = "Hello";
[Link](typeof(box)); // string
box = 100;
[Link](typeof(box)); // number
In this example, the first statement defines a variable box without assigning a value.
Its type is undefined.
Finally, we assign 100 to the box variable. This time, the type of the box variable
changes to number.
As you can see, as soon as the value is assigned, the type of the variable changes.
And you don’t need to explicitly tell JavaScript the type. JavaScript will automatically
infer the type from the value.
Suppose you have a function that returns a product object based on an id:
function getProduct(id){
return {
id: id,
price: 99.5
The following uses the getProduct() function to retrieve the product with id 1 and
show its data:
Output:
The issue with this code is that the product object doesn’t have the Name property. It
has the name property with the first letter n in lowercase.
However, you can only know it until you run the script.
Referencing a property that doesn’t exist on the object is a common issue when
working in JavaScript.
The following example defines a new function that outputs the product information to
the console:
};
showProduct([Link], [Link]);
Output:
To fix the problem of referencing a property that doesn’t exist on an object, you do
the following steps:
interface Product{
id: number,
name: string,
price: number
};
id: id,
price: 99.5
The code editor highlighted the following error on the Name property:
And when you hover the mouse cursor over the error, you’ll see a hint that helps you
to solve the issue:
To solve the problem of passing the arguments in the wrong order, you explicitly
assign types to function parameters:
};
And when you pass the arguments of the wrong types to the showProduct() function,
you’ll receive an error:
A value is anything you can assign to a variable e.g., a number, a string, an array, an
object, and a function.
'Hello'
When you look at this value, you can say it is a string. This value has properties and
methods that a string has.
For example, the 'Hello' value has a property called length that returns the number of
characters:
[Link]('Hello'.length);
It also has many methods like match(), indexOf(), and toUpperCase(). For example:
[Link]('Hello'.toUpperCase()); // HELLO
When you look at the value 'Hello' and describe it by listing the properties and
methods, it would be inconvenient.
A shorter way to refer to a value is to assign it a type. In this example, you
say 'Hello' is a string. Then, you know that you can use the properties and methods
of a string for the value 'Hello'.
In conclusion, in TypeScript:
a type is a label that describes the different properties and methods that a
value has
DataTypes in TypeScript
TypeScript inherits the built-in types from JavaScript. TypeScript types are
categorized into:
Primitive types.
Object types.
Primitive types
Name Description
Undefined Have one value: undefined. It is the default value of an uninitialized variable.
Object types
First, types are used by the TypeScript compiler to analyze your code for
errors.
Second, types allow you to understand what values are associated with
variables.
Type inference describes where and how TypeScript infers types when you don’t
explicitly annotate them.
let counter = 0;
It is equivalent to the following statement:
Likewise, when you assign a function parameter a value, TypeScript infers the type
of the parameter to the type of the default value. For example:
function setCounter(max=100) {
// ...
In this example, TypeScript infers the type of the max parameter to be number.
Similarly, TypeScript infers the following return type of the increment() function
as number:
return counter++;
return counter++;
It uses the best common type algorithm to analyze each candidate type and select
the type that is compatible with all other candidates.
In this case, TypeScript selects the number or null array type (number | null) []) as
the best common type. Note that the | means the OR operator in types.
If you add a string to the items array, TypeScript will infer the type for the items as an
array of numbers and strings: (number | string)[]
The following shows the difference between type inference and type annotations:
TypeScript guesses the type You explicitly tell TypeScript the type
When a function returns the any type, you need to clarify the value.
Summary
Type inference occurs when you initialize variables, set parameter default
values, and determine function return types.
TypeScript uses the best common type algorithm to select the best candidate
types that are compatible with all variables.
TypeScript also uses contextual typing to infer types of variables based on the
locations of the variables.
All numbers in TypeScript are either floating-point values or big integers. The
floating-point numbers have the type number while the big integers get the
type bigint.
The following shows how to declare a variable that holds a floating-point value:
let price: number;
y: number = 200;
Big Integers
The big integers represent the whole numbers larger than 2 53 – 1. A Big integer
literal has the n character at the end of an integer literal like this:
Summary
All numbers in TypeScript are either floating-point values that get the number
type or big integers that get the bigint type.
Summary: in this section, you’ll learn about the TypeScript string data type.
Like JavaScript, TypeScript uses double quotes (") or single quotes (') to surround
string literals:
TypeScript also supports template strings that use the backtick (`) to surround
characters.
The template strings allow you to create multi-line strings and provide string
interpolation features.
The following example shows how to create a multi-line string using the backtick (`):
span multiple
lines
`;
String interpolations allow you to embed the variables into the string like this:
I'm a ${title}`;
[Link](profile);
Output:
I'm John.
I'm a Web Developer.
Summary
Like JavaScript, TypeScript uses double quotes ("), single quotes ('), and
backtick (`) to surround string literals.
In TypeScript, you can declare a boolean variable using the boolean keyword. For
example:
pending = true;
// after a while
// ..
pending = false;
Boolean operator
Operator Meaning
|| Logical OR operator
For example:
// NOT operator
[Link](result); // false
// AND operator
[Link](result); // false
// OR operator
[Link](result); // true
Summary
employee = {
firstName: 'John',
lastName: 'Doe',
age: 25,
};
[Link](employee);
Output:
firstName: 'John',
lastName: 'Doe',
age: 25,
If you reassign a primitive value to the employee object, you’ll get an error :
employee = "Jane";
Error:
The employee object is an object type with a fixed list of properties. If you attempt to
access a property that doesn’t exist on the employee object, you’ll get an error:
[Link]([Link]);
Error:
Note that the above statement works perfectly fine in JavaScript and
returns undefined instead.
To explicitly specify properties of the employee object, you first use the following
syntax to declare the employee object:
let employee: {
firstName: string;
lastName: string;
age: number;
jobTitle: string;
};
And then assign the employee object to a literal object with the described
properties:
employee = {
firstName: 'John',
lastName: 'Doe',
age: 25,
};
Or you can combine both syntaxes in the same statement like this:
let employee: {
firstName: string;
lastName: string;
age: number;
jobTitle: string;
}={
firstName: 'John',
lastName: 'Doe',
age: 25,
};
TypeScript has another type called empty type denoted by {} , which is quite similar
to the object type.
The empty type {} describes an object that has no property on its own. If you try to
access a property on such an object, TypeScript will issue a compile-time error:
[Link] = 'John';
Error:
Summary
The TypeScript object type represents any value that is not a primitive value.
The empty type {} refers to an object that has no property on its own.
Summary: in this section, you’ll learn about the TypeScript array type and its basic
operations.
[Link]('Software Design');
After you define an array of a specific type, TypeScript will prevent you from adding
incompatible values. For example, the following will cause an error:
[Link](100);
When you extract an element from the array, TypeScript infers the type of array
element. For example:
[Link](typeof(skill));
Output:
string
In this example, we extract the first element of the skills array and assign it to
the skill variable.
TypeScript arrays have the same properties and methods as JavaScript. For
example, the following uses the length property to get the number of elements in an
array:
[Link](doubleIt);
Output:
[ 2, 4, 6 ]
The following illustrates how to define an array that holds both strings and numbers:
In this case, TypeScript infers the scores array as an array of string | number. It’s
equivalent to the following:
let scores : (string | number)[];
Summary
Use the let arr: type[] syntax to declare an array of a specific type. Adding a
value of a different type to the array will result in an error.
An array can store values of mixed types. Use the arr: (type1 | type2) [] syntax
to declare an array of values with mixed types (type1, and type2)
TypeScript Tuple
Summary: in this section, you’ll learn about the TypeScript Tuple type and its usage.
The types of elements are known, and need not be the same.
The order of values in a tuple is important. If you change the order of values of
the skill tuple to [5, "Programming"], you’ll get an error:
Error:
For this reason, it’s a good practice to use tuples with data that are related to each
other in a specific order.
For example, you can use a tuple to define an RGB color that always comes in a
three-number pattern:
(r,g,b)
For example:
Since TypeScript 3.0, a tuple can have optional elements specified using the
question mark (?) postfix.
For example, you can define an RGBA tuple with the optional alpha channel value:
Note that the RGBA defines colors using the red, green, blue, and alpha models. The
alpha specifies the opacity of the color.
Summary
A tuple is an array with a fixed number of elements whose types are known.
Summary: in this section, you will learn about the TypeScript any type and how to
use it properly in your code.
Sometimes, you may need to store a value in a variable. But you don’t know its type
when writing the program. And the unknown value may come from a third-party API
or user input.
In this case, you want to opt out of the type checking and allow the value to pass
through the compile-time check.
For example:
result = 1;
[Link](result);
result = 'Hello';
[Link](result);
Output: 6
In this example:
Second, assign number 1 to the result and display its value to the console.
Third, assign the string literal 'Hello' to the result and show its value to the
console.
[Link](currentLocation);
Output:
{ latitude: 10.11, longitude: 12.12 }
In this example, TypeScript infers the value of the currentLocation variable as any.
We assign an object returned by the [Link]() function
the currentLocation variable.
Output:
undefined
The any type provides you with a way to work with the existing JavaScript codebase.
It allows you to gradually opt in and opt out of type-checking during compilation.
Therefore, you can use the any type for migrating a JavaScript project over to
TypeScript.
If you declare a variable without specifying a type, TypeScript assumes that you use
the any type. This feature is called type Inference. TypeScript guesses the type of
the variable. For example:
let result;
Summary
The TypeScript any type allows you to store a value of any type. It instructs
the compiler to skip type-checking.
Use the any type to store a value that you don’t know its type at the compile-
time or when you migrate a JavaScript project over to a TypeScript project.
Sometimes, you will run into a function that expects a parameter that is either a
number or a string. For example:
return a + b;
In this example, the add() function will calculate the sum of its parameters if they are
numbers.
If the parameters are strings, the add() function will concatenate them into a single
string.
If the parameters are neither numbers nor strings, the add() function throws an error.
The problem with the parameters of the add() function is that its parameters have
the any type. It means that you can call the function with arguments that are neither
numbers nor strings, the TypeScript will be fine with it.
add(true, false);
To resolve this, you can use the TypeScript union type. The union type allows
you to combine multiple types into one type.
result = 10; // OK
A union type describes a value that can be one of several types, not just two. For
example number | string | boolean is the type of a value that can be a number, a
string, or a boolean.
Back to the add() function example, you can change the types of parameters from
the any to a union like this:
return a + b;
}
if (typeof a === 'string' && typeof b === 'string') {
return [Link](b);
return a + b;
Summary
A TypeScript union type allows you to store a value of one or several types in
a variable.
In TypeScript, a type is like a set of values. For example, the number type holds the
numbers 1, 2, 3, etc. The string type holds the strings like 'Hi', 'Hello', etc.
The null type holds a single value, which is null.
The never type is a type that holds no value. It is like an empty set.
Since a never type does not hold any value, you cannot assign a value to a variable
with the never type.
For example, you may have an intersection type that can be both a string and a
number at the same time, which is impossible:
This is because string and number are mutually exclusive. In other words, a value
cannot be both a string and a number simultaneously.
Please do not confuse with functions that return void but still return the control to the
caller.
If you have a function that contains an indefinite loop, its return type should be never.
For example:
while (true) {}
In this example, the type of the return type of the forever() function is never.
switch (role) {
case 'admin':
case 'user':
};
How it works.
Step 1. Define a type Role that can be either a string 'admin' or 'user':
Step 2. Create the authorize() function that accepts a value of the Role type and
returns a string:
switch (role) {
case 'admin':
case 'user':
default:
}
};
Summary
Use the never type that holds no value, denoting an impossibility in the type
system.
TypeScript if else
Summary: in this section, you will learn about the TypeScript if...else statement.
TypeScript if statement
if(condition) {
// if-statement
For example, the following statement illustrates how to use the if statement to
increase the counter variable if its value is less than the value of the max constant:
let counter = 0;
counter++;
[Link](counter); // 1
Output:
1
In this example, because the counter variable starts at zero, it is less than
the max constant. The expression counter < max evaluates to true therefore
the if statement executes the statement counter++.
counter++;
[Link](counter); // 100
Output:
100
In this example, the expression counter < max evaluates to false. The if statement
doesn’t execute the statement counter++. Therefore, the output is 100.
If you want to execute other statements when the condition in the if statement
evaluates to false, you can use the if...else statement:
Syntax:-
if(condition) {
// if-statements
} else {
// else statements;
}
The following illustrates an example of using the if..else statement:
counter++;
} else {
counter = 1;
}
[Link](counter);
In this example, the expression counter < max evaluates to false therefore the
statement in the else branch executes that resets the counter variable to 1.
When you want to execute code based on multiple conditions, you can use
the if...else if...else statement.
The if…else if…else statement can have one or more else if branches but only
one else branch.
For example:
discount = 5; // 5% discount
} else {
Output:
You got 15% discount.
This example used the if...else if...else statement to determine the discount based on
the number of items.
If the number of items is less than or equal to 5, the discount is 5%. The statement in
the if branch executes.
If the number of items is less than or equal to 10, the discount is 10%. The statement
in the else if branch executes.
In this example, the assumption is that the number of items is always greater than
zero. However, if the number of items is less than zero or greater than 10, the
discount is 15%.
To make the code more robust, you can use another else if instead of
the else branch like this:
discount = 5; // 5% discount
} else {
Output:
In this example, when the number of items is greater than 10, the discount is 15%.
The statement in the second else if branch executes.
If the number of items is less than zero, the statement in the else branch executes.
Summary
Use the if statement to execute code based on a condition.
case value1:
// statement 1
break;
case value2:
// statement 2
break;
case valueN:
// statement N
break;
default:
//
break;
How it works:
First, the switch...case statement evaluates the expression.
Then, it searches for the first case clause whose expression evaluates to the same
value as the value (value1, value2, …valueN).
The switch...case statement will execute the statement in the first case clause whose
value matches.
If no matching case clause is found, the switch...case statement looks for the
optional default clause. If the default clause is available, it executes the statement in
the default clause.
The break statement that associates with each case clause ensures that the control
breaks out of the switch...case statement once the statements in the case clause
complete.
By convention, the default clause is the last clause in the switch...case statement.
However, it doesn’t need to be so.
The following example shows a simple switch...case example that shows a message
based on the target id:
switch (targetId) {
case 'btnUpdate':
[Link]('Update');
break;
case 'btnDelete':
[Link]('Delete');
break;
case 'btnNew':
[Link]('New');
break;
Output:
Delete
The switch...case statement compares the targetId with a list of values. Because
the targetId matches the 'btnDelete' the statement in the corresponding case clause
executes.
If you have a code that is shared by multiple cases, you can group them. For
example:
let month = 2,
year = 2020;
let day = 0;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
day = 31;
break;
case 4:
case 6:
case 9:
case 11:
day = 30;
break;
case 2:
// leap year
if (((year % 4 == 0) &&
day = 29;
else
break;
default:
Output:
The month 2 in 2020 has 29 days
If the month is 1,3, 5, 7, 8, or 12, the number of days is 31. If the month is 4, 6, 9, or
11, the number of days is 30.
If the month is 2 and the year is a leap year, it returns 29 days, otherwise, it returns
28 days.
Loops In TypeScript
1. For Loop
A for loop repeats a block of code a specific number of times. It’s typically used when
you know how many iterations you want in advance.
Definition:
Condition: The loop checks this condition before each iteration. If it's true, the
loop executes. If it's false, the loop ends.
Increment/Decrement: After each loop iteration, the counter variable is
updated (either incremented or decremented).
Syntax:
2. While Loop
A while loop repeats as long as a specified condition is true. It’s useful when you
don't know how many iterations you need, but you want the loop to run based on a
condition.
Definition:
The loop continues to execute the block of code while the condition is true.
Once the condition becomes false, the loop ends.
Syntax:
while (condition) {
// Code to be executed
}
Example:
let i = 0;
while (i < 3) {
1. You need to add items to the cart until it reaches a specific count.
Example:
3. Do-While Loop
A do-while loop is similar to the while loop, except that it guarantees the loop will run
at least once before the condition is checked.
Detailed Definition:
The block of code inside the do will execute once before the condition is
evaluated, making it useful for situations where you want the code to run at
least once, no matter what.
Syntax:
do {
// Code to be executed
} while (condition);
Example:
let i = 0;
do {
Example:
Do-While Loop
In real-time sometimes you may need to keep prompting the user for their password
until they enter the correct one.
Use Case: Prompting a user to enter a valid password
let enteredPassword;
do {
if (validatePassword(enteredPassword)) {
[Link]("Access granted.");
} else {
}
} while (!validatePassword(enteredPassword));
4. For...of Loop
The for...of loop iterates over the values of iterable objects like arrays, strings, maps,
and sets.
Detailed Definition:
Instead of using a counter, for...of directly gives you the values from the
iterable object.
Syntax:
[Link](fruit);
5. For...in Loop
The for...in loop iterates over the properties of an object (including inherited
properties).
Detailed Definition:
// Code to be executed
Example:
Iterating over object properties: Often used when you need to extract and
process information from an object, such as an API response.
[Link](`${key}: ${user[key]}`);
Functions In TypeScript
TypeScript Functions
Summary: in this section, you will learn about the TypeScript functions and how to
use type annotations to enforce the type checks for functions.
TypeScript functions are the building blocks of readable, maintainable, and reusable
code.
Like JavaScript, you use the function keyword to declare a function in TypeScript:
// do something
}
Unlike JavaScript, TypeScript allows you to use type annotations in parameters and
return the value of a function.
Let’s see the following add() function example:
return a + b;
}
In this example, the add() function accepts two parameters with the number type.
In the add() function example, you can only pass numbers into it, not the values of
other types.
The following code will result in an error because it passes two strings instead of two
numbers into the add() function:
Error:
error TS2345: Argument of type '"10"' is not assignable to parameter of type
'number'
The types of function parameters are also available within the function body for type
checking.
The : number after the parentheses indicate the return type. The add() function
returns a value of the number type in this case.
If a function does not return a value, you can use the void type as the return type.
The void keyword indicates that the function doesn’t return any value. For example:
[Link]([Link]());
The void prevents the code inside the function from returning a value and stops the
calling code from assigning the result of the function to a variable.
When you do not annotate the return type, TypeScript will try to infer an appropriate
type. For example:
In this example, the TypeScript compiler tries to infer the return type of
the add() function to the number type, which is expected.
Summary
A Named Function is one that we write in code and then use whenever we need it by
referencing its name and providing it with some parameters. Named functions come
in handy when we need to call a function several times to give various values to it or
run it multiple times.
function add(a:number, b:number) : number {
return a + b;
}
[Link](add(5, 4));
Output
9
2. Anonymous function:
return a + b;
}
[Link](add(5, 4));
Output
Function Declaration
// Function declaration
[Link](a + b);
// Calling a function
add(2, 3);
Output
Function Expression
// Function Expression
[Link](a + b);
// Calling function
add(2, 3);
Here, the whole function is an expression and the returned value is stored in the
variable. We use the variable name to call the function.
Arrow Function:
It is used to shorten the code. Here we do not use the “function” keyword and use
the arrow symbol.
Example: Below is the example that illustrates the use of the Arrow Function.
[Link](add(3, 2));
Output
This shortens the code to a single line compared to other approaches. In a single
line of code, the function returns implicitly.
Note: When there is a need to include multiple lines of code we use brackets. Also,
when there are multiple lines of code in the bracket we should write return explicitly
to return the value from the function.
Example: This is an example with multiple lines of code in arrow function
if (a > b)
else
[Link](great(3, 5));
Output
b is greater