[Go to site: main page, start]

0% found this document useful (0 votes)
14 views65 pages

Understanding TypeScript Basics

JavaScript is a dynamically typed programming language that enables interactive and dynamic web pages, while TypeScript adds type safety and additional features to enhance development. TypeScript can be integrated into projects either through external .ts files or directly within HTML script tags, although the latter is not recommended for production. The document also covers variable declaration, scope, hoisting, data types, and the use of enums and interfaces in TypeScript.

Uploaded by

zaidsikandar09
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views65 pages

Understanding TypeScript Basics

JavaScript is a dynamically typed programming language that enables interactive and dynamic web pages, while TypeScript adds type safety and additional features to enhance development. TypeScript can be integrated into projects either through external .ts files or directly within HTML script tags, although the latter is not recommended for production. The document also covers variable declaration, scope, hoisting, data types, and the use of enums and interfaces in TypeScript.

Uploaded by

zaidsikandar09
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Java script is a dynamically typed programming language used to make web

pages interactive and dynamic instead of just static. A static page shows the
same content to everyone and doesn’t change unless a developer updates it,
like a simple HTML page. A dynamic page changes its content based on user
actions, data, or other conditions, like a Facebook feed or a shopping cart. In
the browser, Java script can change HTML, update design, store data, and
make HTTP requests using the V8 engine, while on the server with [Link] it
can handle requests, store data in databases, and connect with APIs like GPT.
In normal raw code, we keep HTML, CSS, and JS separate to increase
readability, modularity, and caching efficiency, and when multiple websites
have different CSS and JS, each HTML file links to its respective style and
script files.
One major drawback of plain Java script is that it is dynamically typed,
meaning you can assign any type of value to a variable without checks, which
can cause bugs in bigger projects. To solve this, we have TypeScript, which
includes all Typescript features plus extra features and type safety. Type
safety means you can define types for variables, functions, and objects, so
assigning a wrong type gives an error. For example, let a: string = "hello"; ensures a

is always a string, and a = 123; will throw an error. Extra features mean
TypeScript provides powerful tools that would take a lot of time if written in
plain Typescript and also includes all Typescript concepts, so you can do
everything Typescript can do in the browser, manipulate HTML, update styles,
store data, and make HTTP requests, and on the server with [Link], handle
requests, work with databases, and connect to APIs like ChatGPT. This works
because TypeScript is converted into Typescript, which the browser and
[Link] can understand and execute properly.

Ways to Add Typescript in project


There are 2 ways to use TypeScript:

First way: Use an external .ts file. You write your TypeScript code in that file,
then convert it to Typescript using the TypeScript compiler. After that, you add

Typescript Development 2
the converted .js file to your HTML page using a <script src="..."></script> tag. This
is the right and practical way for real projects.
Second way: Use internal TypeScript directly inside a <script> tag in your
HTML. For this, you need a special loader & compiler because browser don’t
understand Typescript, It can work for small experiments, but strictly don’t
use it for real apps because it is slow, messy, and not maintainable.

Variables in Type Script


Value is a piece of information stored in a box, variable is a name we give to a
memory block where we can store a value, Declare a variable means giving a
memory block a name so you can store a value in it, We use let to declare a
variable whose value can change, and we use const to declare a variable
whose value cannot change. We use var to declare a variable whose value
can change and it can be redeclared with the same name, but we should
avoid var because When you redeclare a variable with var using the same
name, Typescript doesn’t create a new memory block it reuses the old
memory block and overwrites its value. So basically, the old value is lost and
replaced by the new value. This is why using var can be risky, because you
might accidentally overwrite something without realizing it.

Scope
Scope tells us where a variable can be accessed or where not, Where you
declare a variable decides its scope: if a variable is declared inside a function,
it has Function Scope (or Local Scope); if it’s declared inside a block {} like a
loop or if‑statement, it has Block Scope; and if it’s declared outside any
function or block, It has Global Scope, and remember, only const and let
follow these rules; var is always treated as global scope.

Always remember if you write something like function test() { potato = true; } test();
[Link](potato); without using var , let , or const , Typescript will automatically

make potato a global variable, even though it was written inside a function. This
is bad practice, because it can create unwanted global values and cause bugs
later.

Hoisting

Typescript Development 3
Hoisting in Typescript means before the code runs, Typescript first reads and
moves all declarations like var , let , const , function , class , and import to the top of
their scope. Because of this, sometimes you can use a variable or function
before it’s written. But only normal function declarations work fully before
writing. var is hoisted but gets the value undefined , so no error, but no real value.
let and const are hoisted but not ready to use, so using them early gives a

ReferenceError. Function expressions and arrow functions are not hoisted, so


they must be written before calling. Classes are also hoisted but not ready, so
using them early gives an error too. Imports are hoisted and loaded first before
the code.

Rules to Declare Variable


Variable names are case sensitive, which means “a” and “A” are two different
variables. You can use only letters, numbers, underscores (_) and the dollar
sign ($); spaces are not allowed. The first character must be a letter,
underscore, or dollar sign. Reserved words (Built in keywords of the
programming language which have special meaning) cannot be used as
variable names, In Typescript, always give variables descriptive names. Use
camelCase like userName for most variables, you can sometimes use
snake_case like user_name , but avoid kebab-case like user-name because it’s not
allowed, and PascalCase is only for classes like ProductItem , not normal
variables.

Comments
Comments are used to take notes inside the code, and they are not executed
by the compiler.

Data Types
In Typescript there are 7 primitive data types like Number, String, Boolean,
Null, Undefined, BigInt, and Symbol, but we can store arrays, objects, DOM
elements, and functions inside variable too.
Primitives values stored and access directly in memory box and are
immutable.

Primitive values are stored directly inside a box defined by let or const and
can be accessed directly from that box, they are immutable, so their value

Typescript Development 4
cannot be changed once stored, but for let it can be update but for const it
can’t even update.

Non-primitives data types are data structures that are used to store more than
one value. We have built-in data structures that use object types, and we can
also create custom data structures, In Typescript, objects, arrays, and
functions are stored in memory, and the variable you make does not store the
actual value; it stores the reference (address) of that memory box. For arrays
(indexed collection), the reference points to the first box (index 0), and then
Typescript uses that to find the other values. For objects (keyed collection),
each value is stored in memory too, but instead of using numbers like index 0,
we use keys (like name, age) to find the value. Functions are also stored in
memory blocks, and the variable stores the reference to that block. So,
everything is stored by reference, but the way we access it depends on the
type: arrays use numbers (indexes), objects use keys, and functions are
called through their variable reference.

graph TD
A[Data Types & Data Structures]

A --> B[Primitive Data Types]


B --> B1[Number]
B --> B2[BigInt]
B --> B3[String]
B --> B4[Boolean]
B --> B5[null]
B --> B6[Undefined]
B --> B7[Symbol]
B --> B8[unknown]
B --> B9[never]
B --> B10[any]
B --> B11[void]

A --> C[Data Structures]


C --> C1[Data Structures of Object Type]
C1 --> C1a[Object Wrappers]

Typescript Development 5
C1a --> C1a0[Number, String, Boolean]

C1 --> C1b[Keyed Collections]


C1b --> C1b6[Custom Keyed Collections]
C1b6 --> C1b6a[Map]
C1b6 --> C1b6b[Set]
C1b6 --> C1b6c[WeakMap]
C1b6 --> C1b6d[WeakSet]
C1b6 --> C1b6e[Custom Normal Object]
C1b --> C1b7[Built-in Keyed Collections]
C1b7 --> C1b7a[Math]
C1b7 --> C1b7b[Date]
C1b7 --> C1b7c[Error]

C1 --> C1c[Indexed Collections]


C1c --> C1c3[Custom Indexed Collections]
C1c3 --> C1c3a[Array]
C1c3 --> C1c3b[TypedArray]
C1c3 --> C1c3c[Tuple]

C1 --> C1d[Function Collections]


C1d --> C1d1[Built-in Functions]
C1d --> C1d2[Custom Functions]

C --> C2[Custom Data Structures]


C2 --> C2a[Linked List]
C2 --> C2b[Stack]
C2 --> C2c[Queue]
C2 --> C2d[etc]

Primitive Data Types


1. A number is a numeric value. It can be an integer or float

Typescript Development 6
let age = 25; // stores a number

2. A string is a sequence of characters, Under the hood, it works like an array,


but Typescript makes it immutable on purpose by applying some rules to keep
original string safe. String have properties and methods, When we try to use
property like length or use a method on a string, Typescript automatically
wraps the string in a temporary object (this is called autoboxing). The method
runs on this object, a new string is created, and the original string remains
unchanged because it is immutable. Finally, the temporary object is discarded.
That’s why we can read characters by index but cannot change them directly
like in C, Concatenation is used to combine or join values together using + ,
not to perform arithmetic operations.

let name = "Abdullah"; // stores text

3. A Boolean is a data type that can have only two options: true or false.

let isLoggedIn = true; // stores true or false

A Symbol is a special data type in Typescript that creates a unique and hidden
key. When we create a symbol, like let id = Symbol("userId") , the text "userId" is just a
description or label to help us identify it; it is not the actual value of the symbol.
The real symbol value is stored in the variable id . When we use it in an object,
for example let user = { name: "Ali" }; user[id] = 101; , the symbol ( id ) acts as a hidden key,
and the value 101 is stored under that key. This key doesn’t appear when you
print the object, but you can still access it using the same symbol. We can use
[Link] to see the text label we gave to the symbol

Use unknown when you don’t know the value yet. You can assign anything, but
before using it, you must check the type, like let value: unknown = 5; if (typeof value ===
"number") { [Link](value + 1); } . Use any when the value can be anything and

TypeScript won’t check it, like let anything: any = "hello"; [Link](anything + 10); .

Typescript Development 7
BigInt is used for very large numbers that normal numbers can’t handle, like let

big = 12345678901234567890123n; [Link](big); Use to say a variable has no value


null

yet or nothing found, like let user: string | null = null; remember null means a variable
has no value, while 0 is a number, Use undefined when a variable is declared
but not assigned, like let age: number; [Link](age); // undefined . Use void for a
function that does not return anything, like function logMessage(): void { [Link]("Hi");
} . Use never for a function that will never return normally, either because it

throws an error or runs forever, for example function fail(): never { throw new Error("Oops");
} or function infiniteLoop(): never { while(true) {} } . After a never function runs, the code
after it does not execute, You cannot use never with a normal variable,
because it means no value can exist.

function checkValue(x: number): string {


if (x > 0) return "Positive";
else if (x < 0) return "Negative";
else fail(); // never function stops execution
}
[Link](checkValue(0)); // Error thrown by fail(), next code will not run

Enum & Interface


An enum is used to create a set of fixed values for a specific purpose, so you
can only choose from those values and avoid mistakes. You can also assign
values automatically, so when you write the key, the value is set automatically.
Example: enum Direction { North = 1, South = 2, East = 3, West = 4 } let move: Direction = [Link];
[Link](move); // 0 Here North is automatically assigned 0 , South = 1 , etc.
An interface is like a contract or rulebook that defines the shape of an object,
listing which properties and methods it must have; you cannot create an object
from it directly. You can use an interface in a function to make sure the object
passed in has all required properties, or implement it in a class to ensure the
class has all necessary properties and methods, but you still have to write the
full object yourself. Example: interface User { name: string; age: number } function greet(user: User)
{ [Link]([Link]); } A class is a blueprint to create real objects with properties

and methods. You can create multiple objects using the new keyword, and

Typescript Development 8
classes can include constructors and default logic. Example: class Person { name:
string; constructor(name: string) { [Link] = name; } greet() { [Link]("Hello " + [Link]); } } let p = new
Person("Ali"); [Link]();

// Interface
interface User {
name: string;
age: number;
greet(): void;
}

// Implementing interface in a class


class Person implements User {
name: string;
age: number;

constructor(name: string, age: number) {


[Link] = name;
[Link] = age;
}

greet() {
[Link]("Hello " + [Link]);
}
}

let p = new Person("Ali", 25);


[Link](); // Hello Ali

Non Primitive Data type

1: Built in Data Structures of Object Type

1: Object Wrappers for Primitives

Typescript Development 9
Built in
Primitive data types Number, String, and Boolean are auto boxed in Typescript
to create temporary objects, which allows you to use their properties and
methods.

Number Properties & Methods

Number Properties

Use Number.MAX_VALUE to get the largest number, Number.MIN_VALUE for the


smallest positive number, Number.POSITIVE_INFINITY and Number.NEGATIVE_INFINITY
for infinity, [Link] for invalid numbers, [Link] to check tiny
differences, and Number.MAX_SAFE_INTEGER / MIN_SAFE_INTEGER for safe
large/small integers. These help you handle number limits and special
values.

Number Methods
Use toString() to convert number to string, toFixed(n) to round to n decimals,
for n total digits, toExponential(n) for scientific form, valueOf() to get
toPrecision(n)

primitive value, [Link]() to check finite numbers, [Link]() for


whole numbers, [Link]() for invalid numbers, [Link]() for
safe integers, [Link]() and [Link]() to convert strings to
numbers. These help you convert, format, and check numbers.

String Properties & Methods


Properties: String have 2 main Properties length and prototype
To know how many characters are in a string, use length . To see which
function made the string, use constructor . To check the main template or
blueprint of strings, use prototype .

Methods: Method is a function related to an object


To get a character from a string, use at(index) or charAt(index) . To get the
number code of a character, use charCodeAt(index) . For full Unicode number,
use codePointAt(index) .

Typescript Development 10
To make a string from number codes, use [Link]() for normal
codes, and [Link]() for full Unicode codes.

To check or search in a string, use includes() to see if text exists. Use


indexOf() to find first place, lastIndexOf() for last place. Use startsWith() or

endsWith() to check beginning or end. Use search() for pattern search. Use

for first match,


match() matchAll() for all matches. Use localeCompare() to
compare two strings.
To cut or split strings, use slice() to take part, substring() for substring, substr()
for fixed length (old, better use slice/substring). Use split() to break string
into an array.
To change or format strings, use concat() to join, repeat() to repeat, replace() to
change first match, replaceAll() to change all matches. Use padStart() or
to add text at start or end. Use trim() , trimStart() , trimEnd() to remove
padEnd()

spaces. Use toLowerCase() or toUpperCase() to change case. Use


toLocaleLowerCase() or toLocaleUpperCase() for local rules. Use normalize() for

Unicode text. Use toString() or valueOf() to get string value.


Properties like length you just read. Methods like toUpperCase() you call to do
something. Strings do not change themselves; all methods give a new
string.

Boolean Methods

Boolean values are very simple in Typescript. To get the actual true or false
value from a Boolean object, you can use valueOf() , which returns either true
or false . If you want to convert a Boolean into a string, you can use toString() ,
which returns "true" or "false" . Booleans do not have any built-in properties,
so these two methods are all you need to work with them.

2: Keyed Collection
Build in Keyed Collections

Typescript Development 11
Typescript’s built-in keyed collections like Math, Date, and Error are special
objects with predefined methods and properties. Math does number
operations, like [Link](4.6) ; Date handles date and time, like let now = new Date(); ;
Error creates or handles errors, like throw new Error("Something went wrong"); here, new
creates the error object, and throw stops the program immediately. We cannot
store throw new Error() in a variable because it jumps out of the function or block
and the code after it never runs.
Use Math properties like [Link] to get π and Math.E to get Euler’s number. Use
Math methods to do number operations: [Link](4.6) to round a number,
[Link](4.9) for lower integer, [Link](4.1) for higher integer, [Link](16) for

square root, [Link](2,3) for power, [Link]() for random number between 0–
1, [Link](1,5,3) to get maximum, and [Link](1,5,3) to get minimum.

Use Date methods to work with date and time: let date = new Date() creates current
date, [Link]() to get year, [Link]() to get month (0–11), [Link]() to
get day of month, [Link]() to get day of week (0–6), [Link](2025) to set
year, [Link](10) to set month, and [Link](15) to set day and date don’t
have properties
Use Error properties like [Link] to get the message, [Link] to get the
type, and [Link] to see stack trace. Use throw to stop the program when
something goes wrong, for example throw new Error("Oops")

Custom Keyed Collections


Object An object is a data structure used to store data in key-value pair form,
key is a name of variable in which any value is stored, We can store almost all
types of data as object values, like number , string , boolean , null , undefined , BigInt ,
any , or unknown . Symbol is special it creates a unique hidden key, for example

let id = Symbol("userId"); user[id] = 101; . Void and never cannot be stored in objects

because void is for functions that don’t return anything, and never is for
functions that never return and also we can store arrays, objects, DOM
elements, and functions inside an object variable, We can access, modify,
delete, and add data in them, normally we define object using const but you
can use let also, We can access a key in two ways: using the dot notation
( [Link] ) or by passing the key inside square brackets ( object["key"] )

Typescript Development 12
How to make methods inside Object
In Typescript, we can make a function inside an object in three simple ways.
First, by using the old way with the function keyword like greet: function() {
[Link]("Hello " + [Link]); } it works fine but looks a bit long. Second, by using

the shorthand method like greet() { [Link]("Hi " + [Link]); } — this is short, clean,
and mostly used in modern Typescript or inside classes. Third, by using an
arrow function like greet: () => { [Link]("Hey " + [Link]); } it’s short too but doesn’t
have its own this , so it’s not good when you need to use object values.

How to access properties, values and methods of other object


Every object in Typescript has a hidden prototype, which is itself an object
containing many built-in properties and methods like string or array methods. If
we want one object to use the properties, values, and methods of another, we
link them using [Link](child, parent); child will inherit from
parent, giving the first object full access without copying anything. We say
“properties, values, and methods” because functions are sometimes written
directly, not stored in variables. When we assign another object as the
prototype using [Link] , those properties, values, and methods
become accessible through it.

We can’t connect one object directly to more than one prototype because the
last [Link] assignment overwrites the previous one. But by linking
them one after another in a prototype chain, we can still access all data step
by step.
Example:

let obj1 = { a: 10 };
let obj2 = { b: 20 };
let obj3 = { c: 30 };

[Link](obj3, obj2); // obj3 → obj2


[Link](obj2, obj1); // obj2 → obj1

Typescript Development 13
[Link](obj3.a, obj3.b, obj3.c); // 10 20 30

Object Properties, Methods & Keywords


Properties: Objects have some built-in properties, and we can use these
properties to perform actions on the object.
To get all keys of an object, use [Link] . To get all values, use
[Link] . To get both keys and values together, use [Link] . To copy

or merge objects, use [Link] . To stop any changes, use [Link] . To


stop adding new properties but allow updates, use [Link] . To check if
object has a property, use [Link] or [Link] . To list all
property names, use [Link] . To get details of all
properties, use [Link] . To create or modify a property
with options, use [Link] or [Link] . To check if two
objects are the same, use [Link] . To stop adding new properties, use
[Link] . To check if object can have new properties, use

[Link] . To see the main template all objects inherit from, use

[Link] . To see which function or class created an object, use


constructor .

Methods: Methods is a mini function related to a object.


For objects in Typescript, to see all keys use [Link]() , all values use
[Link]() , and both together use [Link]() . To copy an object, use

. To stop changes, use [Link]() or [Link]() . To check a


[Link]()

property, use hasOwnProperty() . To create, read, update, or delete a property,


use [Link] = value , [Link] , [Link] = newValue , and delete [Link]
respectively for full CRUD.

Keywords: Keywords are special words associated with a data type. Here,
they are associated with objects, so they are called object keywords.
To delete a property from an object, use delete . To check if a key exists in
an object, use in . To refer to the current object inside a method, use this .
To create a new object from a constructor or class, use new . To define a

Typescript Development 14
blueprint for objects, use class . To inherit from another class, use extends .
To call parent class constructor or methods, use super .

const user = {
name: 'Ali',
age: 30
};

Add or Update a Value


You can add a new property or change an existing one using dot notation
or bracket notation.

let user = { name: 'Ali', age: 30 };

// Add a new property


[Link] = 'Lahore';
[Link](user);
// Output: { name: 'Ali', age: 30, city: 'Lahore' }

// Update an existing property


[Link] = 31;
[Link](user);
// Output: { name: 'Ali', age: 31, city: 'Lahore' }

// Increment age by 31
[Link] = [Link] + 31; // ✅ valid
[Link](user);
// Output: { name: 'Ali', age: 62, city: 'Lahore' }

Delete a Value

You can remove a property using the delete keyword.

delete [Link];
[Link](user);

Typescript Development 15
// { name: 'Ali', city: 'Lahore' }

Now let’s rebuild user with all properties for the next examples:

const user = {
name: 'Ali',
age: 30,
city: 'Lahore'
};

[Link]()

Gives an array of all property names.

const keys = [Link](user);


[Link](keys);
// ['name', 'age', 'city']

[Link]()

Gives an array of all property values.

const values = [Link](user);


[Link](values);
// ['Ali', 30, 'Lahore']

[Link]()

Gives an array of key–value pairs, each pair inside its own array.

const entries = [Link](user);


[Link](entries);
// [['name', 'Ali'], ['age', 30], ['city', 'Lahore']]

[Link]()

Copies all properties from one or more objects into another.

Typescript Development 16
const details = { country: 'Pakistan' };
const fullUser = [Link](user, details);

[Link](fullUser);
// { name: 'Ali', age: 30, city: 'Lahore', country: 'Pakistan' }

[Link]()

Checks if the object has a given property.

[Link]([Link]('name')); // true
[Link]([Link]('email')); // false

Indexed Collections
Custom Indexed Collections
Normal Array

An array is a data structure which is used to store collection of elements in a


sequence, They can be of the same type or of different types and under the
hood array is an object so that’s why we have array methods, Each element in
an array has its own position, which starts from index 0 and continues
incrementally. In Typescript, an array is also an object, where each index
behaves like a key, and we assign a value to that key, remember you can
create multidimensional arrays.

let fruits = ["apple", "mango", "banana"]; // stores multiple values in a list

Array Properties & Methods


The length property is used to know the total number of elements in an
array.
Method is a function related to a particular object.

Typescript Development 17
map()
Use this method when you want to creates a new array by performing a
function on each item of an existing array.

const numbers = [1, 2, 3];

const doubledNumbers = [Link](number => number * 2);

[Link](doubledNumbers);
// Output: [2, 4, 6]

filter()
Use this method when you want to creates a new array that only includes
items that pass a specific test.

const ages = [12, 18, 25, 6];

const adults = [Link]((age) => age >= 18);

[Link](adults);
// Output: [18, 25]

forEach()
Use this method when you want to runs a function for each item in an
array. It does not create a new array.

const names = ['Ali', 'Usman', 'Sara'];

[Link](name => {
[Link]('Hello, ' + name);
});
// Output:
// Hello, Ali

Typescript Development 18
// Hello, Usman
// Hello, Sara

push() and pop()


Use this method when you want to push() adds an item to the end of the
array pop() removes the last item.

const fruits = ['apple', 'banana'];

[Link]('orange');
[Link](fruits);
// Output: ['apple', 'banana', 'orange']

[Link]();
[Link](fruits);
// Output: ['apple', 'banana']

reduce()
Use this method when you want to combine all items into a single value.
You give it a function with two arguments: the accumulator ( sum ) and the
current item ( n ), and the starting value for sum is written after the comma
at the end of reduce() .

const numbers = [1, 2, 3];


const total = [Link]((sum, n) => sum + n, 0); // 0 is the startin
g value
[Link](total); // 6

Here 0 after the comma is the initial value for sum . If you skip it, reduce will
take the first array element as the starting value automatically. You use

Typescript Development 19
to calculate totals, counts, or merge arrays, like a shopping cart
reduce()

total, vote counts, or flattening arrays.

sort()
Use sort() when you want to arrange the items of an array in order

const numbers = [3,1,2];


[Link]([Link]()); // [1,2,3]
[Link]([Link](n => n > 1)); // 2

find
Use find() when you want to get the first item that matches a condition.

const numbers = [3,1,2];

[Link]([Link](n => n > 1)); // 3

Sort Method
is a method in Typescript which is used to sort array values in
.sort()

ascending order. For text (words), it looks at the first letter of each word
and sorts alphabetically (A to Z), so ["apple","banana","car"] stays
["apple","banana","car"] . For numbers, if you don’t use a compare function,

Typescript treats numbers like text, so [10,2,30].sort() becomes [10,2,30]


because it compares the first digit like letters ("1" < "2" < "3"). To sort
numbers correctly from smallest to biggest, you use .sort((a,b) => a-b) , which
compares the actual values, so [3,1,2].sort((a,b)=>a-b) becomes [1,2,3] .
Inside, the function takes two values at a time ( a and b ) from the array
and compares them. If a - b is negative, a goes before b ; if positive, a
goes after b ; and if 0, their order stays the same. .sort() does not create a
new array, it changes the original array. Typescript keeps comparing two

Typescript Development 20
values at a time until the whole array is sorted, so if the array has 9 values,
it keeps pairing and comparing until even the last value is in the correct
place.

Extra

If you want to get a new array without changing the original, use
methods like concat() to combine arrays, slice() to take part of an array,
filter() to keep only some elements, map() to change each element, flat()

to flatten nested arrays, flatMap() to flatten and map at the same time,
toReversed() to reverse without changing the original, toSorted() to sort

without changing the original, toSpliced() to remove or add elements


without changing the original, and with() to change one element and get
a new array.

If you want to modify the original array directly, use copyWithin() to copy
part of the array inside itself, fill() to fill all or part of the array with a
value, pop() to remove the last element, push() to add elements at the
end, reverse() to reverse the array, shift() to remove the first element,
to sort elements in place, splice() to add or remove elements
sort()

anywhere, and unshift() to add elements at the start.

If you want to get a single value or information from the array, use at()
to get an element at a specific index, every() to check if all elements
pass a test, find() to get the first matching element, findIndex() to get the
index of the first match, findLast() to get the last matching element,
findLastIndex() to get the index of the last match, includes() to check if the
array has a value, indexOf() to get the index of a value, lastIndexOf() to get
the last index of a value, reduce() to combine all elements into one value,
reduceRight() to combine from right to left, some() to check if any element

passes a test, join() to combine elements into a string, and toLocaleString()


to join elements using locale formatting.

If you want to loop over the array or get iterators, use forEach() to run a
function for each element, entries() to get an iterator of [index, value]
pairs, keys() to get an iterator of indexes, and values() to get an iterator of
values. forEach() mainly produces a side effect like printing or updating
something outside, and it does not return anything. The other three

Typescript Development 21
methods give iterators that let you look at elements or indexes step by
step without changing the array.

Arrays of different Types

1. Numbers
You can create an array of numbers like [1, 2, 3, 100, -50] . Use it when you
want to store multiple numeric values together.
2. Strings

You can create an array of strings like ["apple", "banana", "hello"] . Use it when you
want to store multiple text values.
3. Booleans
You can create an array of booleans like [true, false, true] . Use it when you
want to store multiple yes/no or true/false values.
4. Null

You can create an array containing null values like [null, null, null] . Use it when
you want placeholders or empty values in your array.
5. Undefined
You can create an array with undefined values like [undefined, undefined] . Use it
when values are not assigned yet.

6. BigInts
You can create an array of bigints like [10n, 9007199254740991n] . Use it when you
want to store very large integers safely.
7. Objects
You can create an array of objects like [{name:"Ali"}, {age:25}] . Use it when you
want to store structured data with keys and values.

8. Functions
You can create an array of functions like [function(){}, () => [Link]("Hi")] . Use it
when you want to call multiple functions dynamically from the array.
9. Arrays

Typescript Development 22
You can create an array of arrays (nested arrays) like [[1,2],[3,4]] . Use it for
multi-dimensional data, like matrices or grouped values.
10. DOM Elements
You can create an array of DOM elements like [[Link], [Link],

. Use it when you want to store and manipulate


[Link]("div")]

multiple elements from the web page.

Typed Array
Typed arrays are special arrays that store only numbers of a specific type
efficiently. Int8Array stores 8-bit signed integers (-128 to 127), Uint8Array
stores 8-bit unsigned integers (0–255), Uint8ClampedArray stores 8-bit
clamped integers (0–255, useful for colors), Int16Array stores 16-bit signed
integers (-32,768 to 32,767), Uint16Array stores 16-bit unsigned integers (0–
65,535), Int32Array stores 32-bit signed integers (-2,147,483,648 to
2,147,483,647), Uint32Array stores 32-bit unsigned integers (0–
4,294,967,295), Float32Array stores 32-bit floating point numbers, and
Float64Array stores 64-bit floating point numbers. Each typed array can hold
as many elements as memory allows, but each element must stay within the
type’s allowed range. For example: let temps = new Int8Array([-5, 0, 12, -20]);
[Link](temps); → Int8Array [-5, 0, 12, -20] . In short: use typed arrays when you want

to store specific number types efficiently in memory.

Tuple
A tuple is like an array but stricter because it has a fixed length and fixed
types in a specific order. You define the type of each element when you
create it, and you must follow that order exactly. For example, [string, number,
boolean] can store a username, age, and active flag. If you try to put extra

elements or change the order, TypeScript will give an error. Unlike arrays,
which are flexible and can store any number of values of the same or different
types, tuples are for cases where you want specific types in a specific order.
Example: let user: [string, number, boolean]; user = ["Ali", 25, true]; Correct, but ["Ali", true, 25]

Typescript Development 23
Wrong. If you want many values of the same type, use a regular array instead,
like let users: string[] = ["Ali", "Ali", "Ali"];

Destructuring
Destructuring is just a shortcut to use object or array values by directly storing
them inside local variables, and remember for arrays because they don’t have
keys, the variable names can be anything, but for objects you need to use the
exact key names unless you want to rename like key: variable . Also, for arrays,
local variables store values based on their index, so if you want to skip
something you just use a comma , for objects, you can’t “skip” values like
arrays because objects don’t have order or indexes they have keys. If you don’t
want a certain key, you just don’t include it in your destructuring
The rest operator ... works for both: for arrays it stores the remaining values in
a new array, and for objects it stores the remaining keys in a new object. For
example, const person = { name: "Ali", age: 20, city: "Lahore", country: "Pakistan" }; const { name, age, city:

shehar, ...rest } = person; [Link](name, age, shehar, rest); prints Ali 20 Lahore { country: "Pakistan" } .
For arrays, const arr = [10, 20, 30, 40]; const [first,,third, ...others] = arr; [Link](first, third, others);
prints 10 30 [40] .

Key Of Operator
keyof operator in TypeScript gives you all the property names of an object or
interface as a type. For example, if interface User { name: string; age: number; location: string } ,
then type UserKeys = keyof User becomes "name" | "age" | "location" , and you can use any
of these keys like const key: UserKeys = "name" , but not a key that doesn’t exist.

Operators
Operators are used to performs operations on values.
Operator Precedence
Operator Precedence is used to know the order in which operators will be
performed in an expression, like the order of operations in math. Operators
with higher precedence are evaluated first.

Typescript Development 24
For example, in 2 + 3 * 4 , the multiplication ( * ) is done first because it has a
higher precedence than addition ( + ). The expression becomes 2 + 12 , which
equals 14 .

Precedence from highest to lowest:

1. Multiplication (), Division ( / ), Modulus ( % ): These are performed first.

2. Addition ( + ), Subtraction (): These are performed after the multiplication,


division, and modulus operations.

3. Comparison ( < , > , == , etc.): These are performed after arithmetic


operations.

4. Logical AND ( && ): This is performed after comparisons.

5. Logical OR ( || ): This is performed after && .

6. Assignment ( = ): This is performed last.

Operator Associativity
Associativity is used to determines the direction in which operators will
executed in an expression when they have the same precedence. It can be
either left-to-right or right-to-left.
For example, in a-b+c , subtraction and addition have the same precedence.
Their associativity is left-to-right, so the expression is evaluated as (a - b) + c .
Most operators are left-to-right, but some, like the assignment operators, are
right-to-left. For example, a = b = 10 is evaluated from right to left, meaning b is
assigned 10 first, and then a is assigned the value of b .

Operators

Arithmetic Operators
Arithmetic operators are used to perform mathematical calculations: + for
addition ( a + b ), - for subtraction ( a - b ), * for multiplication ( a * b ), / for
division ( a / b ), and % for modulus, which gives the remainder of a division ( a
%b )

Typescript Development 25
Unary Operators

Unary operators work on a single operand, while other operators need two or
more. For example, a++ and a-- are unary operators because they change only
one variable. There are two types: pre and post. In post increment ( a++ ), the
value increases after using the variable, while in pre increment ( ++a ), it
increases before using it. Similarly, in post decrement ( a-- ), the value
decreases after use, and in pre decrement ( --a ), it decreases before use.
When we say “use,” it simply means running that variable, like just writing a++
or ++a ; it doesn’t matter whether you print it or not, the change still happens.
For example, let a = 5; a++; ++a; a--; --a; — here, the value goes from 5 → 6 → 7 → 6
→ 5.

Assignment Operators
Assignment operators are used to assign values to a variable: = assigns a
value ( a = 10 ), += adds and assigns ( a += 5 is the same as a = a + 5 ), -=
subtracts and assigns ( a -= 5 is the same as a = a - 5 ), *= multiplies and assigns
( a *= 5 is the same as a = a * 5 ), and /= divides and assigns ( a /= 5 is the same
as a=a/5 )

Comparison Operators
Comparison operators are used to compare two values and return true or false :
== checks if values are equal, === checks if values and types are equal and
use it in maximum cases unless you does not care about the data type and you
just want to compare value, != checks if values are not equal, !== checks if
values or types are not equal, > means greater than, < means less than, >=

means greater than or equal to, and <= means less than or equal to

Logical Operators
Logical operators are used to combine conditions and return true or false : &&

(AND) returns true if both conditions are true, || (OR) returns true if at least
one condition is true, and ! (NOT) reverses the logical state of a condition

Typescript Development 26
??operator (Nullish Coalescing) gives a default value only if a variable is null
or undefined . For example, let name = null; let defaultName = name ?? "Guest"; gives "Guest"
because name is null, but let age = 0; let defaultAge = age ?? 18; keeps 0 because it’s not
null or undefined

Value Comparison Operators


In Typescript you can compare value in three ways. The == operator checks
values after automatic type conversion (coercion), so "5" == 5 is true. The
strict equality === checks both value and type without conversion, so "5" ===
5 is false but "5" === "5" is true. [Link]() also checks if two values are the

same, but it’s stricter: it doesn’t convert types like == , and unlike === , it treats
-0 and +0 as different and considers NaN equal to NaN . For example, [Link]('1',
1) → false, [Link](NaN, NaN) → true, [Link](-0, 0) → false. In short, use == for
loose comparison with conversion, === for exact value and type, and [Link]()

for the most precise comparison

String Operators

String Operators: + joins two strings together, and += adds one string to
another. Example: let str = "Hello, " + "World!"; str += " Bye!";

Comma Operator (,)


Comma operator , runs several expressions one by one and gives the value of
the last one. For example, let a = (x = 1, y = 2, x + y); first sets x=1 , then y=2 , and
finally a gets 3 , the value of the last expression

Optional operator
Optional operator ? in TypeScript is used to make a property or parameter
optional, which means it may or may not be provided. For example, interface User
{ name: string; age?: number } lets you create let user1: User = { name: "Ali" } without age, or let

user2: User = { name: "Ali", age: 25 } with age.

Conditions in Typescript

Typescript Development 27
Conditional statements are used to take decisions in code, so that we can
perform different actions based on different conditions.

Normal Conditional Statement


If else Statement
An if statement run a piece of code only if a condition is true. When we want
to check multiple conditions one after another and want to execute only one
piece of code from them, we use if–else.
The if–else structure checks each condition in order — if one condition is true,
its code runs and the rest are skipped. The else part runs only when all
conditions are false.
In programming, think of parentheses () as a container for a condition, and
inside these parentheses is a boolean expression.
An expression is a single value or a combination of values, variables, and
operators that produces a value.
A boolean expression is like a question that gives an output — either "Yes" or
"No," or in numeric form, non-zero or zero.

If the result is "Yes" or non-zero → the condition is true.

If the result is "No" or zero → the condition is false.

The boolean expression follows a simple 3-step process:

1. The expression is checked.

2. It gives an output — either "Yes"/"No" or non-zero/zero.

3. Based on that output, the program decides whether to run the code block.

If the condition is true, the block of code runs. If false, it does not. This
process helps the program decide which parts of the code to execute
depending on the condition’s outcome.
For simplicity, we usually just focus on the condition and don’t overthink the
internal steps. The else part is optional but recommended, as it handles the
false case.

Typescript Development 28
If you have a single statement after if or else , you can skip the curly braces
{} — but if there’s more than one statement, you must use curly braces. It is

generally recommended to always use curly braces for clarity and safety.

Normal Coditional Statment

if (condition1) {
// code if condition1 is true
} else if (condition2) {
// code if condition1 is false and condition2 is true
} else {
// code if all conditions are false
}

Ternary Operator

The ternary operator is a shortcut to write a one-line if...else statement. It's a


shortcut that lets you check a condition and return one of two values
depending on whether the condition is true or false. You use it in a single line,
following this structure: condition ? valueIfTrue : valueIfFalse . This makes your code more
compact and readable for simple conditions, It works on 3 operands condition,
true value and false value, Remember, you can use nested ternary operators,
but it’s not recommended. We usually use ternary operators to write short
conditional expressions, Because it is an expression so we can store its result
inside a variable and use it.

Ternery Operator
let age = 20;

let canVote = (age >= 18) ? "You can vote" : "You cannot vote";

[Link](canVote);
// Output: "You can vote"

Typescript Development 29
Switch Statements

A switch statement in Typescript is used to check one variable against several


fixed values instead of writing many if-else statements. It makes code cleaner
and easier to read when the variable has only a few known options, like
numbers or names. Switch checks for exact matches only, not conditions like
> , < , or >= . It’s best used when you know the possible specific values, such
as "red" , "blue" , or "green" . The break statement is used inside switch to stop

further checking, but continue cannot be used there.

let day = "Monday";

switch (day) {
case "Monday":
[Link]("Start of the week");
break;
case "Friday":
[Link]("Weekend is near");
break;
default:
[Link]("Regular day");
}

Conditional Chaining
Optional chaining ( ?. ) is an operator used to safely access properties or
methods of an object without causing an error if something is null or undefined .
Whatever we write before ?. is first checked — if it exists, then the value after
it will be accessed or executed. If it does not exist, it will safely return undefined
instead of giving an error.

const user = { name: "Abdullah", address: { city: "Karachi" } };


[Link]([Link]?.city); // "Karachi"
[Link]([Link]?.phone); // undefined

Typescript Development 30
Template literal
Template literals are strings made with backticks (``) that we used to make
strings and easily embed variables, expressions, or even ternary operators
inside them using ${} This also lets you write on multiple lines; when you
press enter, it's treated as a new line in the string.

const name = "Ali";


const age = 30;

// Using template literals


const greeting = `Hello, my name is ${name} and I am ${age} years old.`;
[Link](greeting);

// Using the old way


const oldGreeting = "Hello, my name is " + name + " and I am " + age + " y
ears old.";
[Link](oldGreeting);

Loop
Loop is used to repeat a block of code, inside loops normally we use unary
operators ( ++ or -- ) on update place to increase or decrease a value by 1, but
if we want to change it by more than 1, we use assignment operators like i=i+

n instead of unary + +

Repetition: Executing the same instructions again and again without changes
Iteration: Executing the same instructions with changes each time is called
iteration

break is used to stop a loop completely, and continue is used to skip the current
loop iteration and move to the next one.

1. for loop is used when you know exactly how many times you want to
repeat a block of code, In [Link], or any code running Typescript, in for
loop first of all the starting value is checked. Then the condition is
evaluated. If it is true, the code block runs. After the first run, if there is an
update, it is applied on the starting value, Then updated value is get, the

Typescript Development 31
condition is checked again based on that value, and the block runs again.
This repeats until the condition becomes false.

for (starting value; condition(how long the loop runs and when it stops); up
date) {
// code
}

Example:

for (let i = 0; i < 5; i++) {


[Link](i);
}

2. while loop is used when you don’t know exactly how many times you want
to repeat a block of code, it keeps running while the condition is true.

while (condition) {
// code
}

Example:

let i = 0;
while (i < 5) {
[Link](i);
i++;
}

3. do while loop is used when you want to execute a block of code at least
one time, regardless of whether the condition is true or false.

do {
// code to be executed

Typescript Development 32
} while (condition);

4. for of Loop: for...of loop is used to perform iteration over arrays and strings
and to get values in this loop we don’t define starting value, condition, or
update— for...of handles that automatically. If more control is needed, a
regular for loop can be used. It counts only actual values or characters, not
the null terminator like in C, When the for...of loop iterates over a string, it
first goes to the memory address stored in the variable (like name ). It gets
the value from that address, stores it in a character variable, and then uses
pointer arithmetic to access the next characters. This process continues
until the entire string or array is processed, we can’t use it with object

let name = "Abdullah";


for (let char of name) {
[Link](char);
}

5. for in Loop: For in Loop: The for...in loop is used to perform iteration over an
object, array, or string to get their keys or indices. We don’t manually
define a starting value, condition, or update for...in automatically goes
through each key or index. For an array or string, it gives the index, which
we use to get the actual value. For an object, it gives the key, which we use
to access its corresponding value.

let student = {
name: "Abdullah",
age: 21,
univeristy: "VU",
isStudying: true,
};

for (let value in student) {

Typescript Development 33
[Link](`${value} value is: ${student[value]}`);
}

Type Inference vs Type Annotation


In TypeScript, type inference means TypeScript automatically figures out the
type of a variable from the value you give it, like let x = 10; where it knows x is a
number. The alternative is explicit type annotation, where you tell TypeScript
exactly what type a variable or value should be, like let x: number = 10; or let name:
string = "Ali";

Type Casting
Type Casting / Type Conversion means changing a value from one data type
to another. This can happen automatically (implicit / type coercion) when the
language converts it for you, like JavaScript turning "5" into 5 when needed,
or manually (explicit) when you tell it to convert using methods like parseInt() ,
parseFloat() , or toString()

Custom Types
To create your own custom type in TypeScript, use the type keyword, give it a
name, then write = and define the type. This is called a type alias. It helps you
give a simple name to any complex type so you can reuse it easily. For
example, type ID = number | string; means the type “ID” can be either a number or a
string. You can then use it like let userId: ID = 123; or let anotherId: ID = "abc"; . This makes
your code cleaner and easier to understand because you don’t have to repeat
long type definitions again and again — you just use the alias name instead.
Next, to allow a variable to store different kinds of values, use a Union Type
with the | symbol. For example, function combine(input1: string | number, input2: string | number) {
return input1 + input2; } means both values can be either a string or a number. But if
you want to merge two types into one single type that includes all their
properties, use an Intersection Type with the & symbol, like type AB = A & B; . This
makes a new type that has everything from both A and B.

Typescript Development 34
// Union Type
function combine(input1: string | number, input2: string | number) {
return [Link]() + [Link](); // converts both to string for sa
fe addition
}

combine(10, 20); // works with numbers


combine("Hello", "Hi"); // works with strings
combine(10, "Hi"); // works with number + string

// Intersection Type
type TypeA = { name: string };
type TypeB = { age: number };

type TypeAB = TypeA & TypeB; // new type has both name and age

let person: TypeAB = { name: "Ali", age: 25 }; // ✅ must have both properti
es

TypeScript Interfaces
Interfaces are simple rules that tell an object or class exactly which properties
and methods it must have, so your code stays clean and consistent; without
interfaces, objects can miss required fields and errors will appear later at
runtime. You use an interface by writing something like interface User { name: string;
age: number } and then creating an object that must follow this shape, Remember,

we can’t create objects from an interface because an interface is not a real


object — it is only a set of rules that tells what properties and methods an
object or class must have. Real objects come from classes or object literals.
Extending interfaces means building a new interface from an old one (like
) so you don’t repeat properties, When we write
interface Admin extends User { role: string }

Admin extends User , it means Admin gets all the rules from User and also adds its

own rules. So Admin must have name , age , and its own role .

Typescript Development 35
Types vs Interfaces: both describe the shape of data, but type can create
unions and advanced combos, while interface is mainly for object/class shapes
and can be extended or merged.
Interface merging means TypeScript allows you to write the same interface
name again, and TypeScript will combine all the fields into one final interface.
This helps when you want to add more rules later or when libraries want to
extend existing interfaces. Hybrid types are special interfaces where one
value behaves like both a function and an object at the same time — that
means you can call it like a function, and also store properties on it like an
object. These features help you write code that is clean, organized, and easy
to understand, Here counter works like a function (you can call it), and also
like an object (it has a count property).
Interface Declaration + Merging Example

interface Box {
size: number;
}

// Merging (adding more rules)


interface Box {
color: string;
}

const myBox: Box = {


size: 10,
color: "red",
};

Hybrid Type Example

interface Counter {
(): number; // function rule
count: number; // object property rule
}

Typescript Development 36
function createCounter(): Counter {
const fn = () => ++[Link];
[Link] = 0;
return fn;
}

const counter = createCounter();


[Link](counter()); // 1
[Link](counter()); // 2
[Link]([Link]); // 2

Type Compatibility
Type Compatibility means whether both types have the same structure or not.
To check this, TypeScript focuses on the shape of the types, not their names.
If two objects have the same properties with the same data types, they’re
compatible and can be assigned, like interface Point { x: number; y: number } let p1: Point = { x:
, but if one has extra or missing
10, y: 20 }; let p2 = { x: 10, y: 20 }; p2 = p1; // same structure

properties like let p3 = { x: 10, y: 20, z: 30 }; p1 = p3; // different structure , TypeScript gives an
error. So use this to check if two types can safely share data by comparing
their structure, not their names.

Classes
What is Class & how to create it
A class is a template used to create objects with properties and methods.
Inside a class, we can directly define property values (like name = "Abdullah"; ), or
we can manually assign them later by writing [Link] = value most of
the time in class we don’t assign values because it is a template we create an
object from a class using the new keyword like let s1 = new Student(); . A class can
also have a special method called a constructor, which automatically runs
when the object is created. We can use it to assign property values or run
some code at the time of object creation.

If we want to use the properties defined inside the class — whether inside
methods, arrays, objects, or template literals — we always write [Link] .
The this keyword means the current object made from that class. We can also

Typescript Development 37
create a variable and instantly use it by writing [Link] while defining or
using it.

How Inheritance works


Inheritance in Typescript means passing down properties and methods from a
parent class to a child class, so that child can use them without rewriting, We
create this connection using the extends keyword like class Child extends Parent {} .

Constructor Overloading
Constructor is a function which runs automatically when new object is created
from the class, If both parent and child classes have a constructor, then inside
the child’s constructor we must first call the parent’s constructor using super() .
This ensures the parent’s part runs first, and also, Typescript requires that you
use super() before using the this keyword. You can also pass arguments inside
super() to send values to the parent constructor if you want it to perform some
operation, To use a parent class method inside the child class, write
[Link]() , and to use or access inherited properties, write

. The same this keyword is also used for accessing properties of


[Link]

the child class itself, Constructor overloading means you can create the same
class using different inputs by making parameters optional.
Others
Access modifiers ( public , private , protected ) control who can read or change a
property, keeping your class safe. Polymorphism means one function or
method can do different things depending on the object that calls it; for
example, the same method sound() makes a dog say “Woof” and a cat say
“Meow”. Abstract classes are base classes you cannot create objects from;
they only guide child classes. Method overriding means if a child class has the
same method, it will replace the parent’s method.

Class + Constructor

class Person {
constructor(public name: string, public age: number) {}
}

Typescript Development 38
const p = new Person("Ali", 20);

Constructor Overloading (using optional params)

class User {
constructor(public name: string, public age?: number) {}
}

const u1 = new User("Hamza");


const u2 = new User("Bilal", 25);

Access Modifiers

class Bank {
public accName = "Ali"; // anyone can access
private balance = 5000; // only inside class
protected pin = 1234; // class + children
}

Inheritance

class Animal {
speak() { [Link]("Animal sound"); }
}

class Dog extends Animal {}


const d = new Dog();
[Link](); // inherited

Polymorphism + Method Overriding

class Animal {
speak() { [Link]("Generic sound"); }
}

Typescript Development 39
class Cat extends Animal {
speak() { [Link]("Meow"); } // overriding
}

new Cat().speak();

Abstract Class

abstract class Shape {


abstract area(): number; // must be implemented by child
}

class Circle extends Shape {


constructor(private r: number) { super(); }
area() { return 3.14 * this.r * this.r; }
}

Type Guards
Type Guards mean telling TypeScript exactly what type a variable currently
has, especially when using custom types or variables that can have more than
one type. Without this, TypeScript can’t know the type, and with type guards
we can perform different actions based on the type. Tools for Type Guards
include: using typeof to check basic types like strings or numbers, instanceof to
see if an object is an instance of a specific class, Type Predicates to create
custom functions that return true/false for a type, and truthiness or equality
checks to narrow types using logical conditions.
Using typeof – for basic types like string or number:

function doubleValue(x: string | number) {


if (typeof x === "string") {
return x + x; // TypeScript knows x is string
} else {
return x * 2; // TypeScript knows x is number

Typescript Development 40
}
}

Using instanceof – to check object class:

class Dog { bark() { [Link]("Woof"); } }


class Cat { meow() { [Link]("Meow"); } }

function makeSound(animal: Dog | Cat) {


if (animal instanceof Dog) {
[Link]();
} else {
[Link]();
}
}

Type Predicates – custom function to check type:

function isString(value: any): value is string {


return typeof value === "string";
}

function printValue(value: string | number) {


if (isString(value)) {
[Link]("String: " + value);
} else {
[Link]("Number: " + value);
}
}

Truthiness & Equality – logical checks to narrow types:

function printLength(value: string | null) {


if (value) { // checks value is not null
[Link]([Link]);
} else {

Typescript Development 41
[Link]("No value");
}
}

Function
Functions
Built in functions
Custom Functions

A function is a piece of code that performs a particular task.


A function has four scenarios to produce a result, It can take arguments and
return a value, like adding numbers and also printing them. It can take
arguments but not return a value, like printing text or saving data to a file. It can
return a value but take no arguments, like increasing a counter and giving back
the new number. And it can neither take arguments nor return a value, like
clearing the screen or turning on a light, we can define function using 2
syntax.
Side Note: A function can be called inside conditions to make decisions like
checking if age is 18 or more; and also as a return value to send data or
another function back.
A callback is a function that we pass inside another function as an argument.
We call it a callback because the main function will call this function when
needed. As a developer, we don’t call it directly; the main function decides
when to run it.
A higher-order function is a function that either takes another function as an
argument or returns a function. So, any function that uses a callback is a
higher-order function.
Hoisting means Typescript moves all function and variable declarations to the
top before running the code. For example, if you write sayHello(); function sayHello() {

, it works because function declarations are hoisted. But with


[Link]("Hello"); }

var , only the declaration goes up, not the value, so [Link](x); var x = 5; prints

undefined . However, hoisting does not work with let , const , arrow functions, or

Typescript Development 42
anonymous functions because they are stored in variables that are not hoisted.
For example, sayHi(); const sayHi = function() { [Link]("Hi"); }; or greet(); const greet = () =>
both cause errors because the functions are assigned to
[Link]("Good Morning");

variables that are not hoisted.

Normal Function

function greet() {
[Link]("Hello!");
}
let sayHello = greet; // you can store a function inside a variable

Arrow Function
// Arrow functions are short and simple, best for small tasks or callbacks a
nd don’t have
// own `this`.

let greet = () => {


[Link]("Hello!");
}
greet(); // We can store function also inside variable and const box

IIFE
An IIFE (Immediately Invoked Function Expression) is a function that runs as
soon as it is created. You wrap it in round brackets and also add round
brackets after it and it executes right away without needing a separate call like
this (function () { [Link]("This runs immediately!"); })(); , It’s mainly used to keep variables
private and prevent them from affecting the global scope.

Closure & Argument Object & Built in function


Inside a function, Scope means where a variable can be accessed, and
Closure means a function can remember variables from its outer scope even
after that outer function has finished running, jaise function outer() { let name = "Ali";

Typescript Development 43
function inner() { [Link](name); } return inner; } let greetClosure = outer(); greetClosure(); yahan inner

function ne name ko yaad rakha. The arguments object lets you access all values
passed to a function without naming them, jaise function greet() { [Link]("You passed
. Built-in Functions are ready-made
" + [Link] + " arguments"); } greet("Ali", 20);

tools JavaScript gives you, like [Link]() or parseInt() .

Typing Functions
Typing Functions mean giving types to function parameters and return
values so TypeScript knows what kind of data to expect and return. Function
Overloading means defining multiple ways to call the same function with
different parameters or types. Rest Parameters let you handle any number of
arguments as an array with a specific type.

function add(a: number, b: number): number; // function overloading


function add(a: string, b: string): string;
function add(a: any, b: any): any {
return a + b;
}

function sumAll(...numbers: number[]): number { // rest parameters


return [Link]((total, num) => total + num, 0);
}

let result1 = add(2, 3); // 5


let result2 = add("Hi, ", "Ali"); // "Hi, Ali"
let total = sumAll(1, 2, 3, 4); // 10

Error Handling
Try, Catch Block
Error handling mean managing problems that can occur during code execution
so the program doesn’t crash. The most common way is using try and catch .
You put the code that might cause an error inside a try block, and if an error
occurs, it jumps to the catch block where you can handle it. The catch block

Typescript Development 44
receives an error object (often called err ) that contains information about the
error.
The err inside catch(err) is just a variable name you choose. Its value comes
from Typescript automatically whenever an error happens inside the try
block, the JS engine creates an error object and passes it into that variable.
You don’t assign it yourself; JS does it for you.

try {
let result = 10 / 0; // some code that may cause error
[Link](result);
} catch (err) {
[Link]("An error occurred:", [Link]);
}

Exception Handling in TypeScript means you can raise errors intentionally


using throw and catch them using try/catch so your program doesn’t crash. For
example:

function divide(a: number, b: number) {


if (b === 0) throw new Error("Cannot divide by zero"); // throw error
return a / b;
}

try {
[Link](divide(10, 0));
} catch (err) {
[Link]("Error occurred:", (err as Error).message); // catch error
}

TypeScript has built-in error objects like Error , TypeError , and ReferenceError .
These objects give information about what went wrong so you can handle
different kinds of errors properly. For instance, you can check the type of error
and respond differently:

try {
let obj: any = undefined;

Typescript Development 45
[Link]([Link]); // ReferenceError
} catch (err) {
if (err instanceof TypeError) [Link]("Type Error!");
else if (err instanceof ReferenceError) [Link]("Reference Error!");
else [Link]("Some other error:", err);
}

Generics
Generics in TypeScript let you create reusable components or functions that
can work with any type instead of a single specific type. This makes your
code flexible and type-safe. For example:

function getArray<T>(items: T[]): T[] {


return new Array().concat(items);
}

let numArray = getArray<number>([1, 2, 3]); // works with numbers


let strArray = getArray<string>(["a", "b", "c"]); // works with strings

Generic Constraints let you limit what types can be used with your generics
so that only certain types are allowed. For example:

function logLength<T extends { length: number }>(item: T) {


[Link]([Link]);
}

logLength([1, 2, 3]); // array has length → works


logLength("Hello"); // string has length → works
// logLength(123); // number has no length → error

Decorators
Decorators in TypeScript let you add extra behavior or information to classes,
methods, or properties without changing their original code. For example,

Typescript Development 46
using a decorator, you can automatically log when a method is called, like in
the code where @log prints the method name and arguments whenever add is
run.

Utility Types
Utility Types in TypeScript are built-in tools that help you manipulate types
easily. Object Utilities like Partial<T>make all properties optional, Pick<T, K>
selects certain properties, Omit<T, K> removes some properties, and Record<K, T>

creates an object with keys K and values T. Union Utilities like Exclude<T, U>
removes types from a union, Extract<T, U> keeps only types that exist in both,
and NonNullable<T> removes null and undefined . Function Utilities like Parameters<T>
gets the parameter types of a function, ReturnType<T> gets its return type, and
Awaited<T> unwraps a Promise. Readonly makes properties unchangeable.

type Person = { name: string; age: number; city?: string };


type PartialPerson = Partial<Person>; // all optional
type NameOnly = Pick<Person, "name">; // only name
type WithoutCity = Omit<Person, "city">; // removes city
type Ages = Record<string, number>; // keys as strings, values as number
s

type Result = Exclude<"a" | "b" | "c", "a">; // "b" | "c"


type Chosen = Extract<"a" | "b" | "c", "a" | "c">; // "a" | "c"
type NonNull = NonNullable<string | null | undefined>; // string

function greet(name: string, age: number) { return name; }


type Params = Parameters<typeof greet>; // [string, number]
type Return = ReturnType<typeof greet>; // string

type ReadonlyPerson = Readonly<Person>; // all properties readonly

TypeScript Modules

Typescript Development 47
TypeScript Modules help you organize and reuse code. Namespaces are used
to organize code internally within a file. External Modules let you import and
export code between different files, like export function greet() {} and import { greet }
from './file' . Ambient Modules are used to declare types for libraries that don’t

provide TypeScript types, using declare module 'library-name' . Augmentation lets


you add properties or types to existing modules, either with namespaces or
globally, for example declare global { interface Window { myProp: string } } .

The TypeScript Ecosystem


In TypeScript development, Build Tools are used to compile and bundle your
code so it can run in browsers or [Link]. Linting helps catch errors and bad
practices early before running the code. Formatting ensures your code style
stays consistent and readable across the project. Useful Packages are
common libraries or tools, like lodash , axios , or tslib , that make coding faster and
easier.

DOM (Document Object Model)


The Window is a large object that the browser automatically creates whenever
you open a new tab. It represents the entire browser window or tab. Inside this
window object, there are many built-in properties (like document , location , history ,
innerWidth , innerHeight ) and methods (like alert() , confirm() , setTimeout() , setInterval() )
that you can use to control or interact with the browser whether it’s your own
or the user’s who opened our site.

However, remember that the window object exists only inside the user’s
browser, not on your server. This means when you write Typescript to
manipulate user window, it runs inside the user’s browser window, You can’t
access or control someone else’s browser window from outside; you can only
control the window of the page or website that your code is running on.
When a web page opens, the browser first reads the HTML and converts it into
a tree-like structure. This structure is stored inside the document object. The
Typescript code runs inside the window object, and whenever we want to
change something on the page, Typescript updates the tree structure inside
the document.

Typescript Development 48
DOM stands for Document Object Model. Here, “Document” means the object
that holds your entire HTML page, and “Model” means the way that HTML is
represented in a tree-like structure inside the object.
The CSS is not stored inside the window object the browser keeps it separately
and applies its styles to the elements inside the document object.
In the DOM, there are three main types of nodes: element nodes, text nodes,
and comment nodes. Most of the time, we work with element nodes because
they represent actual HTML tags like <div> or <p> . When we deal with child
elements, we use properties like firstChild, lastChild to access them. While
looping through child elements, it’s common to use a loop to perform actions
on each child. Also, remember that inline styling (like style="color:red" ) has the
highest priority, so it’s better to avoid using it often, When writing HTML or
Typescript, if you’re already using double quotes outside, then you must use
single quotes inside to avoid errors

CRUD Operations on Elements


To create a new element, use [Link]("tagName") , like let btn =
[Link]("button") . To read or access elements, use selectors such as

[Link]("idName") , [Link]("className") ,
[Link]("div") , or the modern one —
[Link](".className") and [Link](".className") . To update an
element, we can change its content using innerText , innerHTML , or textContent , and
even change its attributes with setAttribute("attrName", "value") . To delete an element,
just call [Link]() and it will disappear from the page. We can also place
elements in the DOM using methods like [Link](el) to add at the end,
[Link](el) to add at the start, [Link](el) to add before, and [Link](el)

to add after.

To see a value as normal text with tags, use [Link]() . To see a value as an
object with all its properties and methods, use [Link]()

CRUD Operations on Styling


To add styling, use [Link] = "value" , like [Link] = "red"

or [Link] = "white" . To read styling, you can check it with

Typescript Development 49
or getComputedStyle(element).propertyName . To update, just
[Link]

change the value again, like [Link] = "green" . And to delete or reset
a style, set it to an empty string like [Link] = "" . You can also
add or remove CSS classes using [Link]("className") or
[Link]("className") , which is an easy and clean way to control styles
from CSS instead of inline.

Events
An event is a change in the state of an object, and we use an event listener to
listen it, Inside the event listener, we have an event type and an event handler
function, which will be executed when the event occurs.
Types of Events
An event trigger is same as event happening. Every node (or element) in the
DOM can produce or respond to an event, There are many types of events like
mouse events (click, hover), keyboard events (key press, key up), form
events (submit, change), and print or window events. These events can
happen because of user actions (like clicking or typing) or sometimes due to
the environment, such as a low battery warning or internet disconnection.
Ways to handle event
Event handling in Typescript means running some code when something
happens on a webpage, like when we click a button or press a key. There are
three simple ways to do it. The old way is to write the event directly in HTML
like <button Me</button> , but it mixes HTML and JS. The
second way is by using a property like [Link] = () => { [Link]("Clicked"); } , which
is cleaner but only one event can work at a time. The best and modern way is
by using addEventListener() , for example [Link]("click", myFunc) , which allows
many events and can be removed later with removeEventListener() . Event handling
helps make webpages interactive and smart.
If we want to remove an event listener, we must pass the same function
reference to removeEventListener() that we used with addEventListener() . That’s why we
store the function inside a variable, because when a function is stored in a
variable, the variable keeps the reference (or address) of the function in
memory. This means both addEventListener() and removeEventListener() point to the

Typescript Development 50
same exact function. If we don’t use a variable and instead write a new
anonymous function, Typescript treats it as a completely different one, so it
won’t get removed.
If you write event code both inside HTML and in Typescript, the Typescript one
will win and run instead of the HTML one. If you use .onclick many times on the
same element, only the last one will work because it replaces the old ones. But
if you use addEventListener() , you can add many event functions for the same
event, and all of them will run.
When an event happens, Typescript gives you an event object with useful info
about what just happened. You can use [Link] to know which event occurred
(like "click" or "keydown"), [Link] to know which element got clicked,
[Link] to know which element the listener is attached to, [Link]

and [Link] to get mouse position, [Link] to check which key was
pressed, [Link]() to stop default behavior (like stopping a form from
submitting), and [Link]() to stop the event from bubbling up.
Remember In Typescript, every HTML element is an object, so you can use
.name (or .id , .class ) to get its attribute, for example <select name="from"></select> and
then in JS [Link]([Link]); // prints "from"

Assertions
In TypeScript, the as syntax lets you manually tell TypeScript the type of a
value, like let x = value as string . as const locks a value so it becomes a literal,
unchangeable type, for example let nums = [1, 2] as const . as any forces a value to be
any type, bypassing type checking, but should be used carefully. Non-null
Assertion ( ! ) tells TypeScript a value is definitely not null or undefined, like
element!.value . The satisfies keyword allows you to check that a value meets a
type requirement without changing its inferred type, for example: let person = {

name: "Ali", age: 20 } satisfies Person .

Strict Mode & The this Keyword


In JavaScript and TypeScript, Strict Mode makes the language more strict by
catching errors early and preventing unsafe actions. The this keyword tells you
the context of a function or method—for example, in a method it refers to the

Typescript Development 51
object, in a standalone function it may be undefined (in strict mode), in event
handlers it refers to the element, and in arrow functions it keeps the this of its
surrounding scope. Explicit Binding uses call , apply , or bind to manually set
what this refers to, and Function Borrowing lets you reuse methods from one
object in another, like using [Link] on an array-like object.

Callback & Handline Promise


Synchronous Programming
In synchronous programming, code runs line by line mean next line doesn’t
start until the previous one finishes, even if it takes a long time or isn’t related.
This makes programs slow and blocks other instructions. For example, if line 3
takes 5 seconds, lines 4 and 5 will wait unnecessarily. That’s why synchronous
programming is inefficient for time-consuming tasks.
Asynchronous Programming
In asynchronous programming, code can continue if the next instruction does
not depend on the current instruction.
Callback
A callback is a function we pass into another function so that it can called it
later when needed, When we pass a function as an argument to another
function's parameter, it is stored just like assigning a function to a normal
variable, and to call it, we use the function’s name followed by parentheses.
In Typescript, any function can be passed as a callback. You can use named
functions like this:

function greet() {
[Link]("Hello!");
}
function execute(callback) {
callback();
}
execute(greet); // Output: Hello!

You can also use anonymous functions directly:

Typescript Development 52
execute(function() {
[Link]("Hi!");
}); // Output: Hi!

Or arrow functions, which are short and modern:

execute(() => {
[Link]("Hey!");
}); // Output: Hey!

Functions can be stored in variables and passed as callbacks:

const sayBye = () => [Link]("Bye!");


execute(sayBye); // Output: Bye!

Even methods from objects can be passed as callbacks:

const obj = {
sayHello: function() {
[Link]("Hello from object!");
}
};
execute([Link]); // Output: Hello from object!

Callback Hell

When multiple dependent tasks are written as nested callbacks, it creates a


structure called callback hell or the Pyramid of Doom. This happens because
each task waits for the previous one to finish, which makes the code deeply
nested, messy, and hard to read, debug, or maintain. Callback hell occurs only
when multiple tasks depend on each other and take time to complete.

function fetchUser(id, callback) {


setTimeout(() => {
[Link]("Fetched user", id);
callback();

Typescript Development 53
}, 1000);
}

fetchUser(1, () => {
fetchUser(2, () => {
fetchUser(3);
});
});

Promises
A Promise is a special Typescript object that is return as a value by function,
by default its state is pending mean it does not send the actual data
immediately. The real data becomes available only when the promise is
fulfilled or rejected. It’s like saying, “If the code runs successfully, I’ll give you
the result. If there’s a problem, I’ll give you an error.” This helps us plan what to
do next. Promises make code cleaner and help us avoid callback hell when
dealing with dependent tasks.

let p = new Promise((resolve, reject) => {


// task here
});

resolve(value) means the task succeeded, and reject(error) means the task failed.
and reject are built-in Typescript functions, so you don’t need to define
resolve

them. You simply use resolve for success and reject for errors, passing a value
or error message inside. In most cases, we consume promises rather than
create them ourselves.
Promise States
A promise can be in three states. When it’s pending, the task is still running
and not finished yet. When it’s fulfilled (resolved), the task finished
successfully and returned a value. When it’s rejected, the task failed and
returned an error. When a system or API returns a promise, it gives a pending
promise object, not the final data. The real data comes only after the promise
is fulfilled or rejected.

Typescript Development 54
Ways to Handle Promise
Handling Promises (.then, .catch, .finally)
When a promise is resolved, it connects to the first .then() in the chain and
passes the resolved value to it. From there, we can chain more .then() calls to
handle results step by step. If any step fails, .catch() handles the error, and
.finally() always runs no matter if the promise succeeds or fails.
Remember Each .then() returns a new promise. Use return inside .then() to pass
the resolved value to the next .then() in the chain.
Example:

let p = new Promise(resolve => {


setTimeout(() => resolve("Data received"), 2000);
});

[Link](res => [Link](res)) // runs on resolve


.catch(err => [Link](err)) // runs on reject
.finally(() => [Link]("Done")); // always runs

Handling Promises using Async Await


To call a function that returns a Promise in TypeScript, we need an async

function, it cannot be used in normal (non-async) functions. We simply add


async to the function declaration. The await keyword pauses the execution of

that async function until the Promise is either resolved or rejected.


Example:

async function run() {


let res1 = await getData(1);
[Link](res1);
let res2 = await getData(2);
[Link](res2);
}

When tasks depend on each other, we use await sequentially — one after
another — to make sure each step finishes before the next starts. But when

Typescript Development 55
tasks are independent and do not rely on each other’s result, they can run in
parallel using separate promises or by using [Link](), which runs all tasks
together without blocking the code.

What Is the Difference Between the these Three Ways to Handle Time-
Consuming Tasks?
When we want to run some code after calling a function that takes time, there
are three main ways. The first is the callback method, where we call a function
and pass another function inside it; this inner function contains the code we
want to run after the main work finishes. The second is using a Promise with
.then()and .catch() methods, where we call a function that returns a Promise,
write the code we want to run later inside .then() , and handle errors inside
.catch() . The third is the async/await method, which is also based on Promises;
we call the function inside an async function, use await before it, and the code
written after await runs only after the Promise finishes. In all three methods, we
first run a function and then attach the code we want to run later, but the
difference is where we place that code: inside the callback, inside
.then() / .catch() , or after await .
In all three cases, the time-taking part runs asynchronously, which means it
runs separately while the rest of the code continues. JavaScript does not stop
or wait for it; the main program moves forward. When the asynchronous task
finishes, JavaScript runs the code we attached — either the callback, the .then()
block, the .catch() block, or the code after await . For example, in all three
methods, if we print "Start" before calling the function, "End" after calling it, and
print the result inside the callback, .then() , or after await , the output will always
be:

Start
End
Data received

This clearly shows that the long task works in the background while the rest of
the code keeps running.

Ways to Handle Asynchronous Tasks

Typescript Development 56
Fire-and-Forget Case (Next instruction does NOT depend on previous time-
taking task)
When the next instruction (whether time-taking or not) is not dependent on a
previous time-consuming task, and we don’t need the result of that task, it’s a
fire-and-forget case, We just start the task and move on it runs in the
background without blocking code, If time-consuming task is non promise like
setTimeout or any async operation we simply call it and move to the next
instruction. If it’s a Promise, we can call it directly and optionally use .catch() to
handle errors. If the Promise is called inside an async function, we use await to
wait for it inside that function, while any code outside the async function runs
normally as the async task continues in the background.
Callback

[Link]("Task 1 started");

setTimeout(() => {
[Link]("Task 1 finished after 2s");
}, 2000); // runs in background

[Link]("Task 2 runs immediately (not dependent)");

Handling Promise with .then, .catch and .finally methods

function downloadFile() {
return new Promise((resolve) => {
setTimeout(() => {
[Link]("File downloaded");
resolve();
}, 2000);
});
}

// Fire-and-forget

Typescript Development 57
downloadFile(); // we don't wait
[Link]("Moving to next step");

Handling Promise with Async/Await

// Simulated async function that returns a Promise


function fetchData() {
return new Promise((resolve) => {
setTimeout(() => {
[Link]("Data fetched");
resolve();
}, 2000);
});
}

// Example: Fire-and-Forget (consuming a Promise)


async function fireAndForget() {
// Consuming the promise using await
await fetchData();
[Link]("Inside async function finished");
}

// Calling without awaiting (fire-and-forget)


fireAndForget();
[Link]("Main code continues");

Dependent Instruction (Next is NOT time-taking but depends on previous)


When the next instruction, which is not time-consuming, depends on a
previous time-taking task, we handle it accordingly. If the first task is a
callback-based function, we call it and run the dependent code inside the
callback without starting a new Promise. If it’s a Promise, we place the
dependent code inside .then() or .catch() . If we’re using async/await, we write
that code after the await statement inside the async function — meaning all
dependent instructions stay within that block.
Callback

Typescript Development 58
function getData(callback) {
setTimeout(() => {
let data = "User Data";
callback(data); // pass result to next step
}, 2000);
}

getData((result) => {
[Link]("Received:", result);
[Link]("Now showing user profile"); // dependent
});

Handling Promise with .then, .catch and .finally methods

function getData() {
return new Promise((resolve) => {
setTimeout(() => resolve("User Data"), 2000);
});
}

getData().then((result) => {
[Link]("Received:", result);
[Link]("Now showing user profile");
});

Handling Promise with Async/Await

function getData() {
return new Promise((resolve) => {
setTimeout(() => resolve("User Data"), 2000);
});
}

async function showProfile() {


const data = await getData();

Typescript Development 59
[Link]("Received:", data);
[Link]("Now showing user profile");
}

showProfile();

Dependent Instructions (Both Are Time-Taking)


When both the next and previous instructions depend on each other and take
time, we structure them carefully in callback chains, .then() chains, or
sequential async/await blocks to ensure proper order.
Callback (Callback Hell)

function fetchUser(id, callback) {


setTimeout(() => {
[Link]("Fetched user", id);
callback();
}, 1000);
}

fetchUser(1, () => {
fetchUser(2, () => {
fetchUser(3);
});
});

Handling Promise with .then, .catch and .finally methods


Each .then() returns a new Promise, so the next .then() waits for the previous
one’s completion.

function fetchUser(id) {
return new Promise((resolve) => {
setTimeout(() => {
[Link](`Fetched user ${id}`);
resolve(`User ${id} data`);
}, 1000);

Typescript Development 60
});
}

// Step-by-step with returns to show flow


fetchUser(1)
.then((res1) => {
[Link]("Returned from 1:", res1);
return fetchUser(2); // returning another Promise
})
.then((res2) => {
[Link]("Returned from 2:", res2);
return fetchUser(3); // again return next Promise
})
.then((res3) => {
[Link]("Returned from 3:", res3);
[Link]("All users fetched successfully");
})
.catch((err) => {
[Link]("Error:", err);
});

Output flow (with 1s delay between each):

Fetched user 1
Returned from 1: User 1 data
Fetched user 2
Returned from 2: User 2 data
Fetched user 3
Returned from 3: User 3 data
All users fetched successfully

Handling Promise with Async/Await

function fetchUser(id) {
return new Promise((resolve) => {
setTimeout(() => {

Typescript Development 61
[Link]("Fetched user", id);
resolve();
}, 1000);
});
}

async function getAllUsers() {


await fetchUser(1);
await fetchUser(2);
await fetchUser(3);
}

getAllUsers();

Set Timeout & Set Interval


In JavaScript, setTimeout and setInterval are used to run code after a delay or
repeatedly at intervals. setTimeout runs a function once after a specified time in
milliseconds, while setInterval runs a function repeatedly at the given time
interval.
Example:

// setTimeout: runs once after 2 seconds


setTimeout(() => {
[Link]("This runs after 2 seconds");
}, 2000);

// setInterval: runs every 1 second


let count = 0;
let intervalId = setInterval(() => {
count++;
[Link]("Interval count:", count);
if (count === 5) clearInterval(intervalId); // stop after 5 times
}, 1000);

Typescript Development 62
Fetch API
fetch is a Typescript function, not a method, to which you give a URL and
parameters, and it calls the API for you. It doesn’t have data itself; the API
responds with promise, and fetch returns that Promise to you. Both fetch and
axios act as middlemen between your code and the API, handling repquests
and delivering responses.
To read the data from the response, we use [Link]() . This function
converts the raw response into a JavaScript object or array. We usually use
with [Link]() because it takes time to convert the raw data into JSON.
await

Once converted, the data can be an array or an object depending on what the
server sends. If the server sends data in square brackets [...] , you get an array
and access items using [0] , [1] , etc. If it sends data in curly braces {...} , you
get an object and access items using keys like [Link] .
Always check if the data is a list (array) using [Link](data) . After that, write
your code to handle both situations: if it is a list, do actions for each item; if it is
an object, do actions directly on its keys. If the data is more complicated,
check if certain keys exist before using them, or make a simple plan (schema)
of what data should look like to avoid errors when the program runs.
There are different formats to work with data when talking to a server. AJAX
stands for Asynchronous JavaScript and XML, but now we usually use JSON
instead of XML. Some people call it AJAJ (Asynchronous JavaScript and
JSON) or just JSON requests. The idea is the same: call the server
asynchronously and get data back. When calling APIs, we also use HTTP
verbs like GET, POST, PUT, DELETE to tell the server what action we want.
Status codes show the result of the request, and headers carry extra
information like content type, authorization, and other metadata for both the
request and the response.

JavaScript Modules
JavaScript Modules let you organize and share code between files. ESM
(ECMAScript Modules) is the modern standard using import and export , like
export function greet() {} and import { greet } from './file' . Common JS is the older [Link]

style, using [Link] and require() , like [Link] = greet; const greet =

require('./file'); .

Typescript Development 63
Iterators & Generators
Iterators let you customize how objects are looped over, so you can control
the sequence of values. Generators are special functions that can pause and
resume execution, using function* and yield , which is useful when you want to
produce values one by one instead of all at once.

Memory Management
This is about how JavaScript handles memory—allocating it for variables and
objects, using it while needed, and releasing it when done. Garbage
Collection automatically cleans up memory that is no longer referenced, so
developers don’t have to manually free memory.

Equality Algorithms
JavaScript has different ways to compare values. Loose equality ( == )
converts types before comparing, strict equality ( === ) compares without
conversion, and [Link] checks if two values are exactly the same using the
SameValue or SameValueZero algorithm, which can handle edge cases like NaN .

Advanced Types
TypeScript provides tools to create flexible and powerful types. Mapped Types
create new types from old ones, Conditional Types change types based on
logic, Template Literal Types combine string patterns, and Recursive Types
allow types to refer to themselves, which is useful for nested structures.

Using Browser Tools


Modern browsers provide DevTools to inspect HTML elements, CSS, and run
console commands. Debugging helps find and fix code errors, while
Performance & Memory tools help detect slow code, memory leaks, or
performance bottlenecks, making your web applications faster and more
reliable.

JSON
JSON is a way to store and share data in a structured format that looks like a
Typescript object, but its data type is string, so we can use string methods on

Typescript Development 64
it. Because it has keys and values like an object, we convert it into a
Typescript object using [Link]() to access values, add, update, delete, loop,
or use object methods. To send data back, we convert it to JSON text using
[Link]() . JSON can store six types of values: strings, numbers, boolean,
arrays, objects, and null, always write keys in strings.

{
"name": "Abdullah",
"age": 20,
"hobbies": ["coding", "reading"],
"isStudent": true
}

Aliases
In [Link], aliases are shortcuts for folder paths to make imports short and
clean. "@/*": ["./*"] means @ points to the root folder of your project—the main
folder you open in VS Code containing [Link] . The * is a wildcard for any
file or folder inside the root. To create your own shortcuts, open [Link] or
[Link] and add paths under [Link] like @components/* , @pages/* ,
@utils/* , and @styles/* . Then when you write import ButtonDeletePost from

"@/components/ButtonDeletePost" , [Link] knows it’s really ./components/ButtonDeletePost ,


letting you avoid long relative paths like ../../components/ButtonDeletePost

Local Storage
Local storage is a small storage space in the browser where Typescript can
save data like names, settings, or scores as key-value pairs. For example, you
can save something using [Link]("name", "Abdullah") , get it back anytime
using [Link]("name") , remove one item with [Link]("name") , or
clear everything using [Link]() . The saved data stays even if the user
closes the browser and will remain there unless the developer or user deletes
it, or a very long period passes, and it is used to remember information in the
browser so the user doesn’t have to enter it again.

How to use libraries inside typescript

Typescript Development 65
First install the library using npm. Then import it inside your TypeScript file and
try to use it. If TypeScript shows no error, it means the library already has
TypeScript support, and nothing else is needed. If TypeScript shows errors like
“Cannot find module” or “has any type,” it means the library does not provide
TypeScript information. In this case, create a folder named types, then create a
file like [Link] inside it. This file will explain the functions that the library
gives you, so TypeScript understands them.
Inside the .[Link] file, write a declare module block. Inside it, list every function you
want to use from that library. For each function, write what input it needs and
what output it gives. Then add the types folder inside your [Link] so
TypeScript can read it. After saving, restart your dev server so TypeScript
starts using this new information.

//To teach TS about one code block


declare module "cool-library" {
export function checkSomething(value: string): boolean;
}

//To teach TS about multiple code blocks


declare module "cool-library" {
export function checkEmail(email: string): boolean;
export function cleanText(text: string): string;
export function getRandomNumber(): number;
}

//To export default code


declare module "is-disposable-email" {
export default function isDisposableEmail(email: string): boolean;
}

Typescript Development 66

You might also like