[go: up one dir, main page]

0% found this document useful (0 votes)
9 views27 pages

Backend Basics

Uploaded by

asharulhaq3
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)
9 views27 pages

Backend Basics

Uploaded by

asharulhaq3
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
You are on page 1/ 27

Module 1:

1.1 Javascript Variables:


Variables are Containers for Storing Data
JavaScript Variables can be declared in 4 ways:
Automatically
Using var
Using let
Using const

In JavaScript, let, var, and const are used to declare variables, but they have some
differences in terms of scope, hoisting, and reassignment.

Understanding Scope, Hoisting and reassignment:

1.1.1 Scope:
Scope refers to the visibility and accessibility of variables and functions within a program.

● In JavaScript, variables have either global scope, function scope (if declared with
var), or block scope (if declared with let or const).
● Global scope means the variable is accessible throughout the entire program.
● Function scope means the variable is accessible only within the function in which it is
declared.
● Block scope means the variable is accessible only within the block (enclosed by curly
braces) in which it is declared.

Difference between Function Scope & Block Scope:

Function Scope:

● Variables declared with var have function scope. This means they are accessible
throughout the entire function in which they are declared, including any nested blocks
within that function.
● Function scope limits the visibility of variables to the function in which they are
defined. Variables declared within a function are not accessible outside of that
function.
● example:

function exampleFunction() {

var x = 10; // x is function-scoped

console.log(x); // Output: 10

}
console.log(x); // Error: x is not defined

Further:
JavaScript has function scope: Each function creates a new scope.
Variables defined inside a function are not accessible (visible) from outside the function.
Variables declared with var, let and const are quite similar when declared inside a function.

Block Scope:

● Variables declared with let and const have block scope. This means they are only
accessible within the block (enclosed by curly braces) in which they are declared.
● Block scope limits the visibility of variables to the block in which they are defined.
Variables declared within a block are not accessible outside of that block.
● Here's an example:

if (true) {

let y = 20; // y is block-scoped

console.log(y); // Output: 20

console.log(y); // Error: y is not defined

Further:
Variables declared inside a { } block cannot be accessed from outside the block:

{
let x = 2;
}
// x can NOT be used here

Variables declared with the var keyword can NOT have block scope.
Variables declared inside a { } block can be accessed from outside the block.

Example
{
var x = 2;
}
// x CAN be used here

Or
{
let x = 10; // x is block-scoped
console.log(x); // Output: 10
}
// Attempting to access x outside the block will result in an error
console.log(x); // Error: x is not defined

Local Scope

Variables declared within a JavaScript function, are LOCAL to the function:

Example

// code here can NOT use carName

function myFunction() {
let carName = "Volvo";
// code here CAN use carName
}

// code here can NOT use carName

Local variables have Function Scope:They can only be accessed from within the
function.Since local variables are only recognized inside their functions, variables with the
same name can be used in different functions.Local variables are created when a function
starts, and deleted when the function is completed.

Global Scope

Variables declared Globally (outside any function) have Global Scope.


Global variables can be accessed from anywhere in a JavaScript program.
Variables declared with var, let and const are quite similar when declared outside a block.

1.1.2 Hoisting:

● Hoisting in JavaScript is a behavior where variable and function declarations are


moved to the top of their containing scope during the compile phase, before the code
is executed. This behavior is specific to variables declared with var, not let or const.
● Variable declarations using var are hoisted, meaning they are effectively "lifted" to the
top of their containing function or global scope.
● Function declarations are also hoisted to the top of their containing scope.
● Only declarations are hoisted, not initializations. Assignments or initializations remain
in place.

1.1.3 Reassignment:
● Reassignment refers to the act of assigning a new value to an existing variable.
● In JavaScript, you can reassign values to variables declared with var, let, or const,
but with some differences:
○ Variables declared with var can be reassigned and redeclared within the
same scope.
○ Variables declared with let can be reassigned but not redeclared within the
same scope.
○ Variables declared with const cannot be reassigned or redeclared within the
same scope, but they can be mutated if they hold a reference to a mutable
object (e.g., an array or object).

1.1.4 Difference Between Let, Var and Const


In JavaScript, let, var, and const are used to declare variables, but they have some
differences in terms of scope, hoisting, and reassignment. Here's a breakdown:
1. var:
○ Variables declared with var are function-scoped. This means they are only
accessible within the function in which they are declared.
○ var variables are hoisted to the top of their containing function or global
scope. This means you can use the variable before it's declared, but its value
will be undefined.
○ You can redeclare and reassign values to var variables.

2. let:
○ Variables declared with let are block-scoped. This means they are only
accessible within the block (enclosed by curly braces) in which they are
declared.
○ let variables are not hoisted to the top of their containing block. They are
hoisted to the top of the block scope, but they are in a "temporal dead zone"
until the actual declaration is encountered.
○ You can reassign values to let variables, but you cannot redeclare them in the
same scope.

3. const:
○ Variables declared with const are also block-scoped.
○ Unlike var and let, you must initialize a const variable when it's declared, and
once initialized, its value cannot be changed.
○ Similar to let, const variables are not hoisted to the top of their containing
block and are also in the temporal dead zone until the actual declaration is
encountered.

Summary,
Use var if you need function scope or if you're working with older JavaScript code.
Use let for block-scoped variables that may change their value.
Use const for variables that should not be reassigned.
1.2 Loops in JavaScript

1.2.1 For Loop


the for loop is a fundamental looping construct used to execute a block of code repeatedly
until a specified condition is met.

Syntax:
for (initialization; condition; increment/decrement) {
// code block to be executed
}

Example:
for (let i = 0; i < 5; i++) {
console.log("The value of i is: " + i);
}

You can also use the for loop to iterate over elements of an array:

Example:

const arr = [1, 2, 3, 4, 5];


for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}

1.2.2 For in loop

● Used to iterate over the properties of an object.


● Iterates over the enumerable properties of an object, including inherited properties
from its prototype chain.
● Typically used with objects, not arrays.
● The syntax is for (variable in object).

Example

const obj = { a: 1, b: 2, c: 3 };
for (let key in obj) {
console.log(key, obj[key]);
}
Output:

a1
b2
c3

1.2.3 For of loop

● Used to iterate over iterable objects such as arrays, strings, maps, sets, etc.
● Iterates over the values of the iterable, not the properties.
● Does not include properties that are not part of the object's prototype chain.
● The syntax is for (variable of iterable).

Example:

const arr = [1, 2, 3];


for (let value of arr) {
console.log(value);
}

Output:

1
2
3

Here's a quick comparison:


● for...in iterates over enumerable properties of an object, whereas for...of iterates over
the values of an iterable.
● for...in is typically used with objects, while for...of is used with iterable objects like
arrays.
● for...in can access both enumerable properties and inherited properties, while for...of
can't access inherited properties.

1.2.4 While Loop

The while loop executes a block of code as long as a specified condition is true.

Its syntax is:


while (condition) {
// code block to be executed
}

Example:
let i = 0;
while (i < 5) {
console.log("The value of i is: " + i);
i++;
}

Output:

The value of i is: 0


The value of i is: 1
The value of i is: 2
The value of i is: 3
The value of i is: 4

1.2.5 Do-While Loop

The do...while loop is similar to the while loop, but the condition is evaluated after executing
the block of code. This means the block of code will always execute at least once.

Its syntax is:

do {
// code block to be executed
} while (condition);

Example:
let i = 0;
do {
console.log("The value of i is: " + i);
i++;
} while (i < 5);

Output:

The value of i is: 0


The value of i is: 1
The value of i is: 2
The value of i is: 3
The value of i is: 4

1.3 OOP Concepts


1.3.1 Object and Object Literals

Objects in JavaScript are collections of key-value pairs where keys are strings (or symbols) and
values can be of any data type, including other objects, functions, and primitive types

Object literals provide a convenient syntax for creating objects in JavaScript. They allow you to
define an object and its properties directly within your code, without the need for a constructor
function. Object literals are enclosed within curly braces {} and consist of zero or more
comma-separated key-value pairs.

Here's an example of an object literal:


const person = {
name: "John",
age: 30,
isStudent: false,
greet: function() {
console.log("Hello, my name is " + this.name);
}
};

1.3.2 Object Constructor Functions

To create an object type we use an object constructor function. An object constructor


function in JavaScript is a function used to create and initialize objects. It serves as a
blueprint for creating multiple objects with similar properties and methods. When a
constructor function is invoked with the new keyword, it creates a new object and sets the
constructor's prototype as the prototype of the newly created object.

Example:
// Object Literal for creating objects
let car = {
name: "Maruti 800",
topSpeed: 89,
run: function() {
console.log("car is running");
}
};
// we have already seen constructors like these:
// new Date();

// Creating a constructor for cars


function GeneralCar(givenName, givenSpeed) {
this.name = givenName;
this.topSpeed = givenSpeed;
this.run = function() {
console.log(`${this.name} Is Running`);
};
this.analyze = function() {
console.log(
`This car is slower by ${200 - this.topSpeed} Km/H than Mercedes`
);
};
}
car1 = new GeneralCar("Nissan", 180);
car2 = new GeneralCar("Marutu Alto", 80);
car3 = new GeneralCar("Mercedes", 200);
console.log(car1, car2, car3);

console.log("Car Name:" + car1.name)


car1.run()
car1.analyze()

Output:
GeneralCar {
name: 'Nissan',
topSpeed: 180,
run: [Function (anonymous)],
analyze: [Function (anonymous)]
} GeneralCar {
name: 'Marutu Alto',
topSpeed: 80,
run: [Function (anonymous)],
analyze: [Function (anonymous)]
} GeneralCar {
name: 'Mercedes',
topSpeed: 200,
run: [Function (anonymous)],
analyze: [Function (anonymous)]
}
Car Name:Nissan
Nissan Is Running
This car is slower by 20 Km/H than Mercedes

Another Example of Bank Account:


function BankAccount(customerName, balance = 0) {
this.customerName = customerName;
this.accountNumber = Date.now();
this.balance = balance;

// this.deposit = function (amount) {


// this.balance += amount;
// };

// this.withdraw = (amount) => {


// this.balance -= amount;
// };
}

// const rakeshAccount = new BankAccount('Rakesh K', 1000);


// const johnAccount = new BankAccount('John Doe');
// rakeshAccount.deposit(5000);
// johnAccount.deposit(1000);
// rakeshAccount.withdraw(2000);

// console.log(rakeshAccount, johnAccount);

// ============================
const accounts = [];
const accountForm = document.querySelector('#accountForm');
const customerName = document.querySelector('#customerName');
const balance = document.querySelector('#balance');

const depositForm = document.querySelector('#depositForm');


const accountNumber = document.querySelector('#accountNumber');
const amount = document.querySelector('#amount');

accountForm.addEventListener('submit', (e) => {


e.preventDefault();
const account = new BankAccount(customerName.value, +balance.value);
accounts.push(account);
console.log(accounts);
});

depositForm.addEventListener('submit', (e) => {


e.preventDefault();
const account = accounts.find(
(account) => account.accountNumber === +accountNumber.value
);
account.deposit(+amount.value);
console.log(accounts);
});

1.3.3 Classes
In JavaScript, classes are a relatively recent addition introduced in ECMAScript 2015 (ES6).
They provide a more familiar syntax for creating objects and dealing with inheritance in a
way that is similar to class-based languages like Java or C++.

1.3.4 Inheritance
Inheritance is a fundamental concept in object-oriented programming (OOP) where a new
class (derived or child class) is created by inheriting properties and behaviors from an
existing class (base or parent class)
class Animal {
constructor(name, color) {
this.name = name
this.color = color
}
run() {
console.log(this.name + " is running!")
}
shout() {
console.log(this.name + " is barking!")
}
}

class Monkey extends Animal {


eatBanana() {
console.log(this.name + " is eating banana")
}
hide() {
console.log(`${this.name} is hiding`)
}
}

let ani = new Animal("Bruno", "white")


let m = new Monkey("Chimpu", "orange")

ani.shout()
m.eatBanana()
m.hide()
// ani.hide() //This will throw an error

1.3.5 Method Overriding


Method overriding is a concept in object-oriented programming where a subclass provides a
specific implementation of a method that is already defined in its superclass. This allows the
subclass to customize or extend the behavior of the inherited method. In JavaScript, method
overriding is commonly used in conjunction with inheritance.

// Parent class
class Employee {
constructor(name, role) {
this.name = name;
this.role = role;
}

// Method to be overridden
introduce() {
console.log(`Hi, I'm ${this.name}, and I work as a ${this.role}.`);
}
}

// Child class inheriting from Employee


class Manager extends Employee {
constructor(name) {
super(name, 'Manager'); // Call parent constructor
}

// Method overriding
introduce() {
console.log(`Hi, I'm ${this.name}, and I manage the team.`);
}
}

// Child class inheriting from Employee


class Developer extends Employee {
constructor(name) {
super(name, 'Developer'); // Call parent constructor
}

// Method overriding
introduce() {
console.log(`Hi, I'm ${this.name}, and I develop software.`);
}
}

// Create instances
let employee = new Employee('John', 'Employee');
let manager = new Manager('Alice');
let developer = new Developer('Bob');

// Call introduce() method on instances


employee.introduce(); // Output: Hi, I'm John, and I work as an Employee.
manager.introduce(); // Output: Hi, I'm Alice, and I manage the team.
developer.introduce();// Output: Hi, I'm Bob, and I develop software.

1.3.6 Constructor Overriding

In JavaScript, constructors cannot be overridden in the same way as regular methods. When
you extend a class, you can provide a new constructor in the subclass, but if you do so, you
must call super() to invoke the constructor of the parent class. This is because JavaScript
does not support method overloading, and the constructor is no exception. The super() call
ensures that the initialization logic of the parent class is executed before any additional logic
in the subclass constructor.

// Parent class
class Employee {
constructor(name, role) {
this.name = name;
this.role = role;
}

introduce() {
console.log(`Hi, I'm ${this.name}, and I work as a ${this.role}.`);
}
}

// Child class extending Employee


class Manager extends Employee {
constructor(name, teamSize) {
super(name, 'Manager'); // Call parent constructor
this.teamSize = teamSize;
}

introduce() {
console.log(`Hi, I'm ${this.name}, a Manager with a team size of ${this.teamSize}.`);
}
}

// Child class extending Employee


class Developer extends Employee {
constructor(name, programmingLanguage) {
super(name, 'Developer'); // Call parent constructor
this.programmingLanguage = programmingLanguage;
}

introduce() {
console.log(`Hi, I'm ${this.name}, a Developer specializing in
${this.programmingLanguage}.`);
}
}

// Create instances
let employee = new Employee('John', 'Employee');
let manager = new Manager('Alice', 10);
let developer = new Developer('Bob', 'JavaScript');

// Call introduce() method on instances


employee.introduce(); // Output: Hi, I'm John, and I work as an Employee.
manager.introduce(); // Output: Hi, I'm Alice, a Manager with a team size of 10.
developer.introduce(); // Output: Hi, I'm Bob, a Developer specializing in JavaScript.
1.3.6 Constructor Overriding
constructor overriding refers to the process of defining a new constructor in a subclass that
replaces the constructor of its superclass. However, unlike method overriding, where the
subclass method can still call the superclass method, constructor overriding does not allow
direct calling of the superclass constructor within the subclass constructor. Instead, the
subclass constructor typically initializes its own properties and may optionally call the
superclass constructor using super() to ensure that the initialization logic of the superclass is
executed

class Animal {
constructor(name) {
this.name = name;
}

introduce() {
console.log(`Hi, I'm ${this.name}.`);
}
}

class Dog extends Animal {


constructor(name, breed) {
super(name); // Call the parent constructor
this.breed = breed;
}

introduce() {
console.log(`Hi, I'm ${this.name}, a ${this.breed} dog.`);
}
}

let animal = new Animal('Generic Animal');


let dog = new Dog('Spot', 'Labrador');

animal.introduce(); // Output: Hi, I'm Generic Animal.


dog.introduce(); // Output: Hi, I'm Spot, a Labrador dog.

In this example:
● The Animal class has a constructor that initializes the name property.
● The Dog class extends Animal and has its constructor that initializes both the name
property (via super()) and the breed property.
● The introduce() method is overridden in both classes to provide different behaviors.
● When creating instances of Animal and Dog, the constructors of both classes are
invoked accordingly, with the subclass constructor replacing the superclass
constructor and optionally calling super() to ensure the superclass initialization logic
is executed.
1.3.7 Static Method
The JavaScript allows static methods that belong to the class rather than an instance of that
class. Hence, an instance is not needed to call such static methods. Static methods are
called on the class directly. It can be of any name. A class can contain more than one static
method. If we define more than one static method with the same name, the last method is
invoked by JavaScript. “this” keyword is used to call a static method within any other static
method in JavaScript.

1.4 Four Pillars in JavaScript


1.4.1 Encapsulation

Encapsulation is the bundling of data (attributes) and methods (functions) that operate on
the data into a single unit or class. This helps in hiding the internal state of an object and
only exposing necessary functionality to interact with it. Encapsulation helps in reducing
complexity, improving reusability, and preventing unintended modification of data.
Encapsulation ensures that the internal state of the object is protected and can only be
accessed or modified through controlled interfaces provided by getter and setter methods,
thus promoting data integrity and security.

1.4.2 Abstraction

Abstraction is the process of hiding the complex implementation details and showing only
the necessary features of an object or class. It allows developers to focus on what an object
does rather than how it does it. Abstraction helps in managing complexity, enhancing
maintainability, and facilitating code reuse.

1.4.3 Inheritance

Inheritance is the mechanism by which a class can inherit properties and methods from
another class (superclass or base class). It promotes code reuse by allowing subclasses to
reuse and extend the functionality of their parent classes. Inheritance enables hierarchical
classification and organization of classes, making the code more scalable and modular.

1.4.4 Polymorphism

polymorphism is primarily achieved through method overriding, which allows objects of


different classes to respond to the same method call in different ways.

// Parent class
class Animal {
constructor(name) {
this.name = name;
}

// Method to make sound


makeSound() {
console.log(`${this.name} makes a sound.`);
}
}

// Child class 1
class Dog extends Animal {
// Method overriding
makeSound() {
console.log(`${this.name} barks.`);
}
}

// Child class 2
class Cat extends Animal {
// Method overriding
makeSound() {
console.log(`${this.name} meows.`);
}
}

// Function to demonstrate polymorphism


function animalSound(animal) {
animal.makeSound();
}

// Creating instances of different classes


const dog = new Dog('Buddy');
const cat = new Cat('Whiskers');

// Calling function with different objects


animalSound(dog); // Output: Buddy barks.
animalSound(cat); // Output: Whiskers meows.

In this example, we have a parent class Animal with a method makeSound(). The Dog and
Cat classes extend the Animal class and override the makeSound() method with their own
implementations. The animalSound() function demonstrates polymorphism by accepting any
object that inherits from the Animal class and calling its makeSound() method. Depending on
the type of object passed, it invokes the appropriate overridden method, exhibiting
polymorphic behavior.
1.5 TypeScript

1.5.1 TypeScript: A Static Type Checker

We said earlier that some languages wouldn’t allow those buggy programs to run at all.
Detecting errors in code without running it is referred to as static checking. Determining
what’s an error and what’s not based on the kinds of values being operated on is known as
static type checking.
TypeScript checks a program for errors before execution, and does so based on the kinds of
values, making it a static type checker. For example, the last example above has an error
because of the type of obj. Here’s the error TypeScript found:

const obj = { width: 10, height: 15 };


const area = obj.width * obj.heigth;

Property 'heigth' does not exist on type '{ width: number; height: number; }'. Did you mean
'height'?

1.5.2 Data Types in TypeScript


Built-in Datatypes:
TypeScript has some pre-defined data-types-

Built-in Data
keyword Description
Type

It is used to represent both Integer as well as


Number number
Floating-Point numbers

Boolean boolean Represents true and false

String string It is used to represent a sequence of characters

Void void Generally used on function return-types

Null null It is used when an object does not have any value

Undefined undefined Denotes value given to uninitialized variable


If variable is declared with any data-type then any
Any any
type of value can be assigned to that variable

User-defined Data Types:


Apart from built-in data types, user can also define its own data type. User-defined types
include Enumerations (enums), classes, interfaces, arrays, and tuple.
NOTE:
In built-in data types,
any:
is a special data-type, also the super data-type of all data types. If a variable is declared with
any data type then we can assign any type value to that variable.

1.5.3 Interfaces

In TypeScript, interfaces are a powerful way to define the shape or structure of an object.
They are like a contract that specifies which properties and methods an object must have.
This allows you to enforce a certain structure across your codebase, making it more
predictable and maintainable.

Example:
interface Person {
name: string;
age: number;
}

function greet(person: Person) {


return `Hello, ${person.name}!`;
}

let myFriend = { name: "Alice", age: 30 };

console.log(greet(myFriend)); // Outputs: Hello, Alice!

Interface for Array:


// Interface for Array
interface ForList {
[index:number]: string
}
let newArray: ForList = ["Interface", "for", "Array"];
console.log(newArray);

Properties of Interfaces

1. Extending properties:
TypeScript allows interfaces to extend existing interfaces. This enables us to add new
properties to an interface while reusing properties from another.

Example:
interface For_Array {
var1: string;
}
interface For_List extends For_Array {
var2: string;
}
Here for list interface contain var2 property and extend the var1 property of For_Array
property.

2. Optional Properties

You can also define properties that may or may not be present in the implementing object.
These properties are marked with a ? symbol.

Example:
interface Car {
brand: string;
model?: string; // Optional property
}

function displayCar(car: Car) {


let carInfo = `Brand: ${car.brand}`;
if (car.model) {
carInfo += `, Model: ${car.model}`;
}
console.log(carInfo);
}

let myCar = { brand: "Toyota" };


displayCar(myCar); // Outputs: Brand: Toyota

let herCar = { brand: "BMW", model: "X5" };


displayCar(herCar); // Outputs: Brand: BMW, Model: X5

In this example, the Car interface has a required brand property and an optional model
property marked with ?. The displayCar function takes a Car object as an argument and
displays its brand and model if the model is provided. When calling displayCar, you can pass
objects with or without the model property.

3. Read Only Property


Readonly Properties: You can specify properties that cannot be changed after initialization
by using the readonly modifier.
interface Point {
readonly x: number;
readonly y: number;
}

4. Function Properties: Interfaces can also define function types.

Example:
interface ForFunc {
(key: string, value?: string): void;
}

function printInfo(key: string, value: string): void {


console.log(`${key} for ${value}`);
}

const newFunc: ForFunc = printInfo;


newFunc("Interface", "Function");

Explanation:

Interface Definition (ForFunc):

interface ForFunc {
(key: string, value?: string): void;
}

● Here, ForFunc is an interface that describes a function type.


● It specifies a function that takes two parameters: key (required, of type string) and
value (optional, of type string).
● The function returns void, meaning it does not return any value.

Function Implementation (printInfo):

function printInfo(key: string, value: string): void {


console.log(`${key} for ${value}`);
}
● printInfo is a function that matches the structure defined by the ForFunc interface.
● It takes a key (required) and a value (optional) as parameters and logs a message to
the console.
Assigning the Function to a Variable:

const newFunc: ForFunc = printInfo;


● Here, newFunc is declared as a variable of type ForFunc.
● It's assigned the printInfo function, which matches the function type specified by the
ForFunc interface.

Calling the Function:

newFunc("Interface", "Function");
● newFunc is called with two arguments: "Interface" for key and "Function" for value.
● Since value is optional in the ForFunc interface, it's valid to call newFunc with just
one argument (key)

1.5.4 Classes

What Are Classes?


In TypeScript, classes are blueprints for creating objects. They encapsulate data (properties)
and behavior (methods) into a single unit. By defining classes, you can organize your code,
promote reusability, and enhance readability.
Key Components of TypeScript Classes
1. Methods: Functions defined within a class that perform specific actions.
2. Constructors: Special methods called when an object is created from a class.
Constructors initialize class properties.
3. Properties: Variables associated with a class instance.
4. Inheritance: The ability to create new classes based on existing ones, allowing code
reuse and specialization.

Access Modifiers (public, private, and protected)


● public: Properties and methods are accessible from outside the class.
● private: Restricts access to within the class itself.
● protected: Allows access within the class and its subclasses.

1.5.5 What is Enum ?

In TypeScript, an enum, short for "enumeration," is a data type that allows you to define a set
of named constants. Enums are useful when you have a fixed set of values that a variable
can take. They make your code more readable and maintainable by providing meaningful
names to these values.

Place to use an enum: Enums should be used whenever there is a small set of fixed values
available that are closely related and further these values are known at compile time.
1.5.6 Generics
Generics in TypeScript allow you to create reusable components and functions that can work
with a variety of data types while still maintaining type safety. Generics enable you to define
functions, classes, and interfaces with placeholders for types, which are filled in when the
component is used.

Generic Functions:
Generics in functions allow you to define placeholders for the types of parameters and return
values. This makes functions more flexible and reusable across different data types.

Syntax:
function functionName<T> (returnValue : T) : T {
return returnValue;
}

Example 1: In this example, we have created a generic function that can accept any type of
data, we need to pass the value in the parameter by giving them any kind of data type and
then we can reverse that value by the use of the reverseArray function.

function reverseArray<T>(array: T[]): T[] {


return array.reverse();
}

const strArray: string[] = reverseArray(["Java", "Python", "C++"]);


const numArray: number[] = reverseArray([1, 2, 3, 4, 5]);
const boolArray: boolean[] = reverseArray([false, true]);

console.log(strArray);
console.log(numArray);
console.log(boolArray);

Generic Interfaces:
Interfaces can also be generic, allowing you to define placeholders for types in interface
declarations.

Example 2: In this example, we have created a generic interface by using that we are
creating object and string type of value and printing them in the console.

interface Resource<T> {
id: number;
resourceName: string;
data: T;
}
const person: Resource<object> = {
// Generic interface with objects
id: 1,
resourceName: 'Person',
data: {
name: 'John',
age: 25,
}
}
console.log(person);
const employee: Resource<string[]> =
{
// Generic interface with strings array
id: 2,
resourceName: 'Employee',
data: ['Employee 1', 'Employee 1']
}
console.log(employee);

Generic Classes:
Generics in classes enable you to create classes with members whose types are specified
by the user when the class is instantiated.

Example 3: consider a real-world example of a generic class: a Queue data structure. A


queue is a collection of elements that follows the First-In-First-Out (FIFO) principle, meaning
that the element that was added first will be the first to be removed. We'll create a generic
class to represent this Queue

class Queue<T> {
private elements: T[] = [];

enqueue(element: T): void {


this.elements.push(element);
}

dequeue(): T | undefined {
return this.elements.shift();
}

isEmpty(): boolean {
return this.elements.length === 0;
}

peek(): T | undefined {
return this.elements[0];
}

size(): number {
return this.elements.length;
}
}

// Example usage:
const stringQueue = new Queue<string>();
stringQueue.enqueue("first");
stringQueue.enqueue("second");
stringQueue.enqueue("third");

console.log("Size:", stringQueue.size()); // Output: 3

console.log("Peek:", stringQueue.peek()); // Output: first

console.log("Dequeue:", stringQueue.dequeue()); // Output: first

console.log("Size after dequeue:", stringQueue.size()); // Output: 2

Generic Type Constraints:


TypeScript allows you to constrain the types that can be used with generics using type
constraints. This ensures that only certain types are allowed.

TypeScript constraints are used in generic type declarations to restrict the types that can be
used as type arguments for the generic. Constraints allow you to specify that a generic type
parameter must meet certain criteria, such as implementing a particular interface, having a
specific method, or extending a specific class. This ensures type safety and enhances code
predictability.

Syntax:
function functionName<T extends ConstraintType>(param: T): ReturnType {
// Function implementation
}

Parameters:
● T is the generic type parameter.
● extends is used to specify the constraint.
● ConstraintType is the type or interface that T must extend or implement.
● param is the parameter that must be of type T.
● ReturnType is the return type of the function.

Example 1:
function whatIsLength<Type extends { length: number }>
(x: Type, y: Type) {
if (x.length >= y.length) {
return ("x is larger than y");
} else {
return ("x is smaller than y");;
}
}

const ans = whatIsLength([4, 0], [8, 9, 0]);


console.log(ans);

const ans1 = whatIsLength("abcde", "bb");


console.log(ans1);

1.5.7 Union Type


A union type in TypeScript allows a variable to have one of multiple types. It's represented
using the | operator between the types. This means that a variable declared with a union
type can hold values of any of the specified types. Union types are useful when a function or
variable can accept or return multiple types of values.

1.5.8 Type Guards


Type guards in TypeScript are a way to narrow down the type of a variable within a
conditional block. They allow you to perform runtime checks on the type of a variable and
have TypeScript infer the correct type within the scope of that block. Type guards help
ensure type safety and enable more precise type inference.

1.6 POSTGRES SQL

1.6.1 CRUD BASIC OPERATIONS

CREATE TABLE employee(


employeeid INT,
fullname VARCHAR(25),
department VARCHAR(25),
salary INT,
workmode VARCHAR(25)
);
SELECT * FROM employee;

INSERT INTO employee (employeeid,fullname,department,salary,workmode)


VALUES
(1, 'John Doe', 'IT', 50000, 'Full-time'),
(2, 'Jane Smith', 'HR', 45000, 'Part-time'),
(3, 'Michael Johnson', 'Finance', 60000, 'Full-time'),
(4, 'Emily Davis', 'Marketing', 55000, 'Part-time'),
(5, 'David Brown', 'IT', 52000, 'Full-time'),
(6, 'Sarah Wilson', 'Finance', 58000, 'Full-time'),
(7, 'James Taylor', 'HR', 47000, 'Part-time'),
(8, 'Jennifer Martinez', 'Marketing', 53000, 'Full-time'),
(9, 'Robert Anderson', 'IT', 51000, 'Part-time'),
(10, 'Linda Thomas', 'HR', 46000, 'Full-time');

SELECT*FROM employee; --to retrieve data from a database, we use select statment.

-- selecting specific column


SELECT employeeid,salary FROM employee;

-- to add column in exister column, use alter table statement


alter table employee
add yearsofservice INTEGER;

select * FROM employee;

--to remove a column we have to use first alter table and then drop keyword.
ALTER TABLE employee
DROP yearsofservice;

-- adding column again


alter table employee
add yearsofservice INTEGER;

--update statement used for modification in existing records of table.


-- BE CAREFUL WHEN USING WHERE CLAUSE, IF YOU OMIT THE WHERE CLAUSE,
ALL RECORDS WILL BE UPDATED!
UPDATE employee
SET yearsofservice = 5
WHERE salary > 50000;

SELECT*FROM employee;

-- UPDATE MULTIPLE COLUMNS


UPDATE employee
SET department = 'Operation', workmode = 'Full-Time'
where employeeid = 10;
select*FROM employee;

-- to change data type or the size of a table column we have to use alter table / alter column
-- we want to change the data type of workmode into just 0 or 1, so its data type should be
integer
-- ALTER TABLE employee
-- ALTER COLUMN workmode type integer;

/* Delete Statement
Be careful when deleting records in a table! Notice the WHERE clause in the DELETE
statement.
The WHERE clause specifies which record(s) should be deleted.
If you omit the WHERE clause,
all records in the table will be deleted!.*/

Delete from employee


where employeeid = 6;

SELECT employeeid FROM employee;

/* DELETE ALL RECORDS


it is possible to delete all records without deleting the table. this means that table structure,
attributes and indexes will be intact

example */
delete from employee; -- delete all record in the employee table
SELECT*FROM employee;

-- TRUNCATE TABLE
/* because we omit the where clause in the delete statement above, all records will be
deleted from the employee table.
the same would have been achieved by using the TRUNCATE TABLE statement*/

TRUNCATE TABLE employee;


SELECT*FROM employee;

-- DROP TABLE
DROP TABLE employee;

-- SELECT * FROM employee; it will give an error that employee does not exist

You might also like