Skip to main content

TypeScript Loops

Loops are essential control structures in programming that allow you to execute a block of code multiple times. In TypeScript, loops operate just like in JavaScript but with the added benefit of type safety. Understanding loops is crucial for efficient programming, as they help automate repetitive tasks and process collections of data.

Introduction to Loops in TypeScript

When programming, you'll often encounter situations where you need to perform the same operation multiple times. Instead of writing the same code repeatedly, loops provide a way to repeat code execution with different values until a certain condition is met.

TypeScript supports several types of loops:

  1. for loops
  2. while loops
  3. do-while loops
  4. for...of loops (for iterable objects)
  5. for...in loops (for objects)

Let's explore each of these loop types with examples and use cases.

The for Loop

The for loop is one of the most common loops in TypeScript. It consists of three parts: initialization, condition, and increment/decrement.

Basic Syntax

typescript
for (initialization; condition; increment/decrement) {
// Code to be executed
}

Example: Counting from 1 to 5

typescript
for (let i: number = 1; i <= 5; i++) {
console.log(`Count: ${i}`);
}

Output:

Count: 1
Count: 2
Count: 3
Count: 4
Count: 5

In this example:

  • let i: number = 1 initializes a counter variable
  • i <= 5 is the condition that must be true for the loop to continue
  • i++ increments the counter after each iteration

Practical Example: Processing an Array

typescript
const fruits: string[] = ['Apple', 'Banana', 'Orange', 'Mango', 'Strawberry'];
const fruitBasket: string[] = [];

for (let i = 0; i < fruits.length; i++) {
fruitBasket.push(`Fresh ${fruits[i]}`);
console.log(`Added ${fruits[i]} to the basket`);
}

console.log('Basket contents:', fruitBasket);

Output:

Added Apple to the basket
Added Banana to the basket
Added Orange to the basket
Added Mango to the basket
Added Strawberry to the basket
Basket contents: [ 'Fresh Apple', 'Fresh Banana', 'Fresh Orange', 'Fresh Mango', 'Fresh Strawberry' ]

The while Loop

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

Basic Syntax

typescript
while (condition) {
// Code to be executed
}

Example: Counting Down from 5

typescript
let countdown: number = 5;

while (countdown > 0) {
console.log(`Countdown: ${countdown}`);
countdown--;
}

console.log('Blast off!');

Output:

Countdown: 5
Countdown: 4
Countdown: 3
Countdown: 2
Countdown: 1
Blast off!

Practical Example: Random Number Generation

typescript
let attempts: number = 0;
let foundTarget: boolean = false;

// Keep generating random numbers until we get one greater than 0.9
while (!foundTarget) {
attempts++;
const randomValue: number = Math.random();
console.log(`Attempt ${attempts}: Generated ${randomValue.toFixed(4)}`);

if (randomValue > 0.9) {
foundTarget = true;
console.log(`Success! Found value > 0.9 after ${attempts} attempts`);
}

// Safety check to avoid infinite loop during demonstration
if (attempts >= 10) break;
}

Output (will vary):

Attempt 1: Generated 0.2415
Attempt 2: Generated 0.6124
Attempt 3: Generated 0.1842
Attempt 4: Generated 0.9234
Success! Found value > 0.9 after 4 attempts

The do-while Loop

The do-while loop is similar to the while loop, but it executes the code block at least once before checking the condition.

Basic Syntax

typescript
do {
// Code to be executed
} while (condition);

Example: Basic do-while

typescript
let count: number = 0;

do {
console.log(`Count is: ${count}`);
count++;
} while (count < 3);

Output:

Count is: 0
Count is: 1
Count is: 2

Practical Example: User Input Validation

Here's a pseudo-code example simulating user input validation:

typescript
function getUserInput(): string {
// In a real application, this would get input from the user
// Here we'll simulate with predefined values
const possibleInputs = ['invalid', 'invalid again', 'valid input'];
return possibleInputs[Math.floor(Math.random() * possibleInputs.length)];
}

let userInput: string;
let attempt: number = 1;

do {
console.log(`Attempt ${attempt}: Requesting valid input...`);
userInput = getUserInput();
console.log(`Received: "${userInput}"`);

if (userInput !== 'valid input') {
console.log('Invalid input, please try again');
attempt++;
}

// Prevent infinite loop in this simulation
if (attempt > 5) {
console.log('Too many attempts, breaking loop');
break;
}
} while (userInput !== 'valid input');

if (userInput === 'valid input') {
console.log('Successfully received valid input!');
}

Output (will vary):

Attempt 1: Requesting valid input...
Received: "invalid"
Invalid input, please try again
Attempt 2: Requesting valid input...
Received: "valid input"
Successfully received valid input!

The for...of Loop

The for...of loop iterates over iterable objects like arrays, strings, and other collections.

Basic Syntax

typescript
for (const element of iterable) {
// Code to be executed
}

Example: Iterating Through an Array

typescript
const colors: string[] = ['red', 'green', 'blue', 'yellow'];

for (const color of colors) {
console.log(`Color: ${color}`);
}

Output:

Color: red
Color: green
Color: blue
Color: yellow

Practical Example: Processing Data Objects

typescript
interface Product {
id: number;
name: string;
price: number;
}

const inventory: Product[] = [
{ id: 1, name: 'Laptop', price: 1200 },
{ id: 2, name: 'Phone', price: 800 },
{ id: 3, name: 'Tablet', price: 500 },
{ id: 4, name: 'Headphones', price: 150 }
];

let totalValue: number = 0;

for (const product of inventory) {
console.log(`${product.name}: $${product.price}`);
totalValue += product.price;
}

console.log(`Total inventory value: $${totalValue}`);

Output:

Laptop: $1200
Phone: $800
Tablet: $500
Headphones: $150
Total inventory value: $2650

The for...in Loop

The for...in loop iterates over all enumerable properties of an object.

Basic Syntax

typescript
for (const key in object) {
// Code to be executed
}

Example: Iterating Through Object Properties

typescript
const person = {
firstName: 'John',
lastName: 'Doe',
age: 30,
occupation: 'Developer'
};

for (const property in person) {
console.log(`${property}: ${person[property]}`);
}

Output:

firstName: John
lastName: Doe
age: 30
occupation: Developer

Practical Example: Dynamic Form Configuration

typescript
interface FormConfig {
[key: string]: {
type: string;
required: boolean;
label: string;
};
}

const userFormConfig: FormConfig = {
username: {
type: 'text',
required: true,
label: 'Username'
},
email: {
type: 'email',
required: true,
label: 'Email Address'
},
age: {
type: 'number',
required: false,
label: 'Age'
}
};

console.log('Form Field Configuration:');
for (const field in userFormConfig) {
const config = userFormConfig[field];
console.log(
`- ${config.label} (${field}): ` +
`Type: ${config.type}, ` +
`Required: ${config.required ? 'Yes' : 'No'}`
);
}

Output:

Form Field Configuration:
- Username (username): Type: text, Required: Yes
- Email Address (email): Type: email, Required: Yes
- Age (age): Type: number, Required: No

Loop Control Statements

TypeScript provides statements to control the behavior of loops:

break Statement

The break statement terminates the current loop and transfers control to the statement following the loop.

typescript
for (let i = 1; i <= 10; i++) {
if (i === 5) {
console.log('Breaking loop at i = 5');
break;
}
console.log(`Current value: ${i}`);
}
console.log('Loop completed');

Output:

Current value: 1
Current value: 2
Current value: 3
Current value: 4
Breaking loop at i = 5
Loop completed

continue Statement

The continue statement skips the current iteration and proceeds to the next iteration of the loop.

typescript
for (let i = 1; i <= 5; i++) {
if (i === 3) {
console.log('Skipping iteration at i = 3');
continue;
}
console.log(`Processing value: ${i}`);
}
console.log('Loop completed');

Output:

Processing value: 1
Processing value: 2
Skipping iteration at i = 3
Processing value: 4
Processing value: 5
Loop completed

Nested Loops

You can also nest loops within each other for more complex operations.

typescript
console.log('Multiplication Table:');

for (let i = 1; i <= 3; i++) {
let row = '';
for (let j = 1; j <= 3; j++) {
row += `${i * j}\t`;
}
console.log(row);
}

Output:

Multiplication Table:
1 2 3
2 4 6
3 6 9

Loop Performance Considerations

When working with loops, keep these performance considerations in mind:

  1. Loop optimization: Pre-calculate array lengths when possible
  2. Choose the right loop: Different loops perform better in different scenarios
  3. Avoid expensive operations inside loops
typescript
// Less optimal
const items: number[] = [1, 2, 3, 4, 5];
for (let i = 0; i < items.length; i++) {
// items.length is recalculated in each iteration
console.log(items[i]);
}

// More optimal
const optimizedItems: number[] = [1, 2, 3, 4, 5];
const len = optimizedItems.length;
for (let i = 0; i < len; i++) {
// Length is calculated once
console.log(optimizedItems[i]);
}

Real-World Applications

Data Processing Pipeline

typescript
interface DataRecord {
id: number;
value: string;
isValid: boolean;
}

// Sample data
const records: DataRecord[] = [
{ id: 1, value: 'First Record', isValid: true },
{ id: 2, value: 'Corrupted', isValid: false },
{ id: 3, value: 'Third Record', isValid: true },
{ id: 4, value: '', isValid: false },
{ id: 5, value: 'Fifth Record', isValid: true }
];

// Process records
const validRecords: DataRecord[] = [];
const invalidRecords: DataRecord[] = [];

for (const record of records) {
if (record.isValid && record.value.length > 0) {
// Process valid records
const processedRecord = {
...record,
value: record.value.toUpperCase()
};
validRecords.push(processedRecord);
console.log(`Processed valid record ${record.id}`);
} else {
// Collect invalid records for error reporting
invalidRecords.push(record);
console.log(`Skipped invalid record ${record.id}`);
}
}

console.log('\nProcessing Summary:');
console.log(`Total records: ${records.length}`);
console.log(`Valid records: ${validRecords.length}`);
console.log(`Invalid records: ${invalidRecords.length}`);

Output:

Processed valid record 1
Skipped invalid record 2
Processed valid record 3
Skipped invalid record 4
Processed valid record 5

Processing Summary:
Total records: 5
Valid records: 3
Invalid records: 2

Building a Dynamic UI Component

Here's an example of how loops might be used to create a dynamic UI component in a TypeScript-based front-end application:

typescript
interface MenuItem {
id: string;
label: string;
url: string;
children?: MenuItem[];
}

function generateMenu(items: MenuItem[]): string {
let menuHTML = '<ul class="menu">';

for (const item of items) {
menuHTML += `<li id="${item.id}">`;
menuHTML += `<a href="${item.url}">${item.label}</a>`;

// Handle nested menu items with recursion
if (item.children && item.children.length > 0) {
menuHTML += generateMenu(item.children);
}

menuHTML += '</li>';
}

menuHTML += '</ul>';
return menuHTML;
}

const menuStructure: MenuItem[] = [
{
id: 'home',
label: 'Home',
url: '/home'
},
{
id: 'products',
label: 'Products',
url: '/products',
children: [
{ id: 'electronics', label: 'Electronics', url: '/products/electronics' },
{ id: 'clothing', label: 'Clothing', url: '/products/clothing' }
]
},
{
id: 'about',
label: 'About Us',
url: '/about'
}
];

console.log(generateMenu(menuStructure));

Output:

html
<ul class="menu"><li id="home"><a href="/home">Home</a></li><li id="products"><a href="/products">Products</a><ul class="menu"><li id="electronics"><a href="/products/electronics">Electronics</a></li><li id="clothing"><a href="/products/clothing">Clothing</a></li></ul></li><li id="about"><a href="/about">About Us</a></li></ul>

Summary

Loops are essential programming constructs that allow you to:

  1. Execute code repeatedly based on conditions
  2. Process collections of data efficiently
  3. Automate repetitive tasks
  4. Implement complex algorithms

In TypeScript, you have several loop types at your disposal:

  • for loops for known iteration counts
  • while loops for condition-based iterations
  • do-while loops for at least one execution
  • for...of loops for iterables
  • for...in loops for object properties

Each loop type has its ideal use cases, and mastering them will make your TypeScript code more efficient and readable.

Exercises

To practice what you've learned about TypeScript loops, try these exercises:

  1. Write a function that uses a loop to reverse a string
  2. Create a loop that filters an array of numbers to separate odd and even values
  3. Implement a nested loop to generate a pattern of asterisks forming a triangle
  4. Use a for...of loop to find the maximum value in an array of numbers
  5. Create a function that uses loops to check if a string is a palindrome

Additional Resources

Happy coding with TypeScript loops!



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)