Sitemap

JavaScript + Backend Bootcamp

Day 7 : TypeScript Fundamentals

--

Today we begin TypeScript.

TypeScript builds on JavaScript by adding static type checking. Type annotations are removed during compilation, producing JavaScript that browsers and Node.js can execute. (TypeScript)

TypeScript is heavily used in:

  • Node.js
  • Express.js
  • React
  • Large applications
  • Production backend systems
  • Team-based development

Recommended Reading 📖

Before starting today’s exercises, read:

From JavaScript to TypeScript: How TypeScript Improves Code Quality

This article introduces the transition from JavaScript to TypeScript and explains how type safety improves code quality.

Today’s lesson expands on that foundation with practical TypeScript setup, compiler configuration, functions, arrays, objects, interfaces, type aliases, unions and API typing.

1. What Is TypeScript?

TypeScript is JavaScript with an additional type system.

JavaScript:

let age = 22;
age = "Twenty Two";

JavaScript allows the value to change from a number to a string.

TypeScript:

let age: number = 22;
age = "Twenty Two";

TypeScript reports an error:

Type 'string' is not assignable to type 'number'.

This helps identify mistakes before running the application.

2. Why Use TypeScript?

TypeScript provides:

  • Type safety
  • Better autocomplete
  • Earlier error detection
  • Safer refactoring
  • Better code documentation
  • More predictable function inputs and outputs
  • Easier collaboration in large projects

TypeScript-aware editors can provide property suggestions, navigation, refactoring tools and errors while you write code. (TypeScript)

3. Create a TypeScript Project

Create a project folder:

mkdir typescript-day-7
cd typescript-day-7

Initialize the project:

npm init -y

Install TypeScript locally:

npm install --save-dev typescript

Create a TypeScript configuration:

npx tsc --init

Create:

src/app.ts

Suggested structure:

typescript-day-7/
│
├── src/
│ └── app.ts
│
├── package.json
├── package-lock.json
└── tsconfig.json

4. Configure tsconfig.json

Use a beginner-friendly configuration:

{
"compilerOptions": {
"target": "ES2022",
"module": "CommonJS",
"rootDir": "./src",
"outDir": "./dist",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
}
}

Important options:

  • target: JavaScript version generated
  • module: module system
  • rootDir: TypeScript source directory
  • outDir: compiled JavaScript directory
  • strict: enables strict type-checking rules

The official TypeScript documentation recommends strict checking for new projects; "strict": true activates the strictness options together. (TypeScript)

5. Compile TypeScript

Add this to src/app.ts:

const message: string = "Hello TypeScript";
console.log(message);

Compile:

npx tsc

Run the generated JavaScript:

node dist/app.js

Output:

Hello TypeScript

TypeScript code is compiled into JavaScript because TypeScript type annotations are not directly executed by JavaScript runtimes. (TypeScript)

6. Watch Mode

Instead of compiling manually after every change:

npx tsc --watch

TypeScript will watch your files and recompile when they change.

7. Basic Types

String

let username: string = "Ravi";
console.log(username);

Number

let age: number = 22;
console.log(age);

Boolean

let isAdmin: boolean = true;
console.log(isAdmin);

Use lowercase primitive type names such as string, number and boolean, rather than wrapper types like String, Number and Boolean. (TypeScript)

8. Type Inference

TypeScript can often determine a variable’s type automatically.

let city = "Hyderabad";

TypeScript infers:

string

This produces an error:

city = 100;

You do not need to write explicit types everywhere.

Get Bhaskar Chowdary’s stories in your inbox

Join Medium for free to get updates from this writer.

Prefer inference when the type is obvious:

const country = "India";
const score = 95;
const isLoggedIn = true;

9. Arrays

Array of Strings

const fruits: string[] = [
"Apple",
"Banana",
"Mango"
];
console.log(fruits);

Array of Numbers

const marks: number[] = [80, 90, 75];
console.log(marks);

Generic Array Syntax

const cities: Array<string> = [
"Hyderabad",
"Delhi",
"Chennai"
];

Both number[] and Array<number> are valid ways to define typed arrays. (TypeScript)

10. Tuples

A tuple is an array with a fixed structure.

let user: [string, number];
user = ["Ravi", 22];

This produces an error:

user = [22, "Ravi"];

Example:

const response: [number, string] = [
200,
"Success"
];
console.log(response);

Tuples describe arrays with known element positions and types. (TypeScript)

11. Functions in TypeScript

Parameter Types

function add(a: number, b: number) {
return a + b;
}
console.log(add(10, 20));

This produces an error:

add("10", 20);

Return Type

function multiply(
a: number,
b: number
): number {
return a * b;
}

String Return Type

function greet(name: string): string {
return `Hello ${name}`;
}
console.log(greet("Ravi"));

12. Void Return Type

Use void when a function does not return a useful value.

function showMessage(message: string): void {
console.log(message);
}
showMessage("Welcome");

13. Optional Parameters

Use ? for optional parameters.

function greet(
name: string,
city?: string
): string {
if (city) {
return `Hello ${name} from ${city}`;
}
  return `Hello ${name}`;
}
console.log(greet("Ravi"));
console.log(greet("Ravi", "Hyderabad"));

14. Default Parameters

function welcome(
name: string = "Guest"
): string {
return `Welcome ${name}`;
}
console.log(welcome());
console.log(welcome("Ravi"));

15. Arrow Functions with Types

const subtract = (
a: number,
b: number
): number => {
return a - b;
};
console.log(subtract(10, 5));

Short form:

const square = (value: number): number =>
value * value;

16. Object Types

const student: {
name: string;
age: number;
passed: boolean;
} = {
name: "Ravi",
age: 22,
passed: true
};
console.log(student);

17. Optional Object Properties

const user: {
name: string;
email?: string;
} = {
name: "Ravi"
};

email is optional.

18. Readonly Properties

const product: {
readonly id: number;
name: string;
} = {
id: 1,
name: "Laptop"
};

This produces an error:

product.id = 2;

The name property can still be updated:

product.name = "Gaming Laptop";

19. Interfaces

Interfaces define the structure of objects.

interface User {
name: string;
age: number;
isAdmin: boolean;
}
const user: User = {
name: "Ravi",
age: 22,
isAdmin: false
};
console.log(user);

Interfaces are especially useful for:

  • User data
  • Product data
  • API responses
  • Database models
  • Function parameters

TypeScript uses structural typing, meaning a value is accepted when it has the required shape. (TypeScript)

20. Interface with Optional and Readonly Properties

interface Product {
readonly id: number;
name: string;
price: number;
description?: string;
}
const product: Product = {
id: 1,
name: "Keyboard",
price: 1500
};

21. Interface with Functions

interface Calculator {
add(a: number, b: number): number;
subtract(a: number, b: number): number;
}
const calculator: Calculator = {
add(a, b) {
return a + b;
},
subtract(a, b) {
return a - b;
}
};
console.log(calculator.add(5, 3));

22. Type Aliases

A type alias creates a reusable name for a type.

type UserID = string | number;
let firstUserId: UserID = 101;
let secondUserId: UserID = "USER-102";

Object example:

type Student = {
name: string;
marks: number;
passed: boolean;
};
const student: Student = {
name: "Ravi",
marks: 85,
passed: true
};

Type aliases can represent objects, unions, primitives and tuples. (TypeScript)

23. Interface vs Type Alias

Use an interface primarily for object structures:

interface User {
name: string;
age: number;
}

Use a type alias when creating:

  • Union types
  • Tuple types
  • Primitive aliases
  • More complex composed types
type Status = "pending" | "success" | "failed";

Interfaces can be reopened and extended, while a type alias cannot be redeclared in the same way. (TypeScript)

24. Union Types

A union allows more than one possible type.

let userId: string | number;
userId = 101;
userId = "USER-101";

Function example:

function printId(id: string | number): void {
console.log(`ID: ${id}`);
}
printId(100);
printId("ABC-100");

A union type represents a value that may be one of several specified types. (TypeScript)

25. Literal Types

Literal types restrict values to exact choices.

type UserRole = "admin" | "user" | "editor";
let role: UserRole = "admin";

This produces an error:

role = "manager";

Backend example:

type RequestMethod =
| "GET"
| "POST"
| "PUT"
| "DELETE";

26. any

any disables most type checking.

let data: any = "Hello";
data = 100;
data = true;
data.notExistingMethod();

Avoid any whenever possible because it removes much of TypeScript’s protection. The noImplicitAny strictness option helps detect values that unintentionally become any. (TypeScript)

27. unknown

unknown can hold any value, but it must be checked before use.

let value: unknown = "Hello TypeScript";
if (typeof value === "string") {
console.log(value.toUpperCase());
}

Prefer unknown over any when receiving uncertain data.

28. Type Narrowing

Type narrowing checks a value before using it.

function formatValue(
value: string | number
): string {
if (typeof value === "string") {
return value.toUpperCase();
}
  return value.toFixed(2);
}
console.log(formatValue("hello"));
console.log(formatValue(25));

29. Type Assertions

A type assertion tells TypeScript that you know a more specific type.

const input = document.querySelector(
"#username"
) as HTMLInputElement;
console.log(input.value);

Type assertions do not convert data or perform runtime validation; they only affect the compiler. (TypeScript)

Use them carefully.

30. Typing Async Functions

An async function returns a Promise.

async function getMessage(): Promise<string> {
return "Data loaded";
}
getMessage().then((message) => {
console.log(message);
});

Object example:

interface User {
id: number;
name: string;
}
async function getUser(): Promise<User> {
return {
id: 1,
name: "Ravi"
};
}

31. Type-Safe API Response

interface ApiUser {
id: number;
name: string;
email: string;
}
async function fetchUsers(): Promise<ApiUser[]> {
const response = await fetch(
"https://jsonplaceholder.typicode.com/users"
);
if (!response.ok) {
throw new Error(
`Request failed: ${response.status}`
);
}
const data: unknown = await response.json(); return data as ApiUser[];
}

Important:

TypeScript types do not automatically validate external API data at runtime. Later, we’ll use a validation library such as Zod before trusting incoming data.

32. Mini Project — Typed Student Result System

interface Student {
readonly id: number;
name: string;
marks: number;
}
type Grade = "A" | "B" | "C" | "Fail";function calculateGrade(marks: number): Grade {
if (marks >= 90) {
return "A";
}
if (marks >= 70) {
return "B";
}
if (marks >= 40) {
return "C";
}
return "Fail";
}
function printResult(student: Student): void {
const grade = calculateGrade(student.marks);
console.log(`
ID: ${student.id}
Name: ${student.name}
Marks: ${student.marks}
Grade: ${grade}
`);
}
const student: Student = {
id: 1,
name: "Ravi",
marks: 85
};
printResult(student);

This project combines:

  • Interfaces
  • Function types
  • Literal types
  • Return types
  • Readonly properties
  • Conditions

Common Beginner Mistakes

Using wrapper types

Avoid:

let name: String = "Ravi";
let age: Number = 22;

Prefer:

let name: string = "Ravi";
let age: number = 22;

Using any everywhere

Avoid:

function processData(data: any): any {
return data;
}

Prefer meaningful types:

interface User {
id: number;
name: string;
}
function processUser(user: User): User {
return user;
}

Adding unnecessary annotations

Unnecessary:

const name: string = "Ravi";

Type inference is enough:

const name = "Ravi";

Explicit types are most valuable for:

  • Function parameters
  • Return types
  • Public APIs
  • Complex objects
  • Data received from outside the application

Important Concepts Learned Today

✅ TypeScript setup
✅ tsconfig.json
✅ Compilation with tsc
✅ Strict mode
✅ Basic types
✅ Type inference
✅ Arrays
✅ Tuples
✅ Function types
✅ Optional parameters
✅ Default parameters
✅ Object types
✅ Interfaces
✅ Type aliases
✅ Union types
✅ Literal types
✅ any and unknown
✅ Type narrowing
✅ Type assertions
✅ Async TypeScript
✅ Type-safe API structures

Homework

Create:

  1. Typed calculator
  2. Student result system
  3. Product inventory using interfaces
  4. User-role system using literal types
  5. Async function returning typed user data
  6. Convert one previous JavaScript exercise into TypeScript

Practice Challenge

Build a typed order calculator:

Product: Keyboard
Price: 1500
Quantity: 2
Total: 3000

Use:

  • interface
  • Typed function parameters
  • Number return type
  • Template literals

Day 8

Advanced TypeScript

We’ll learn:

  • Advanced unions
  • Intersection types
  • Generics
  • Generic constraints
  • Classes
  • Access modifiers
  • Inheritance
  • Type guards
  • Utility types
  • keyof
  • Async TypeScript patterns
  • Avoiding unsafe types
  • TypeScript best practices

Mini Project:

User Management System

--

--

Bhaskar Chowdary
Bhaskar Chowdary

I believe in There is No Problem Without Solution