Skip to main content

How to use TypeScripe for loops

Loops in TypeScript help you iterate over data structures, process collections, and control program flow. Whether you're working with arrays, objects, or other iterable types, for loops offer precise control over how you traverse and manipulate data. Let's explore different ways to use for loops effectively in your TypeScript code.

Iterating over Arrays with a For Loop

A common use for for loops is to iterate over arrays. You can do this with a traditional for loop or the more concise for...of loop. Here's how you can use both:

// Basic array iteration with index
const numbers = [1, 2, 3, 4, 5];
for (let i = 0; i < numbers.length; i++) {
console.log(numbers[i]);
}

// Using a for...of loop
for (const number of numbers) {
console.log(number);
}

The indexed loop gives you access to array positions, while for...ofprovides a cleaner syntax when you just need the values. Choose based on whether you need the index in your loop body.

Using For...Of Loops for Object Iteration

When working with object types in TypeScript, you have several ways to iterate over their properties. The forloop can handle keys, values, or both using built-in Object methods:

// Iterating over an object's keys
const person = { name: 'John', age: 30 };
for (const key in person) {
console.log(key);
}

// Iterating over an object's values
for (const value of Object.values(person)) {
console.log(value);
}

// Iterating over an object's entries
for (const [key, value] of Object.entries(person)) {
console.log(`${key}: ${value}`);
}

Each approach serves a different purpose: for...in iterates over enumerable properties, Object.values() lets you work directly with values, and Object.entries() gives you access to both keys and values in a single loop.

Implementing Index-Based Iteration with For Loops

Sometimes, you need to iterate over an array while tracking each element's index. This can be done with a traditional for loop or by using the entries() method, which returns an iterator over the array's indices and values.

// Basic index-based iteration
const colors = ['red', 'green', 'blue'];
for (let i = 0; i < colors.length; i++) {
console.log(`Color at index ${i}: ${colors[i]}`);
}

// Using a for...of loop with an index
const colorsWithIndex = colors.entries();
for (const [index, color] of colorsWithIndex) {
console.log(`Color at index ${index}: ${color}`);
}

The traditional index loop works best when you need precise control over the counter variable, while entries() provides a more concise way to access both index and value together. For performance-critical Convex code that processes large arrays, check out the tips in Convex's TypeScript best practices guide.

Iterating over Collections with For Loops

TypeScript allows for iterating over different collections, like Sets and Map<K, V>, using for...of loops. This makes it easy to process the elements of these collections.

// Iterating over a Set
const uniqueNumbers = new Set([1, 2, 3, 4, 5]);
for (const number of uniqueNumbers) {
console.log(number);
}

// Iterating over a Map
const personMap = new Map([
['name', 'John'],
['age', 30],
]);
for (const [key, value] of personMap) {
console.log(`${key}: ${value}`);
}

Each collection type in TypeScript is iterable by default, meaning you can use them directly with for...of loops. This behavior follows the same patterns used by the Convex database's data structures, making it natural to work with both local and database collections.

Using For Loops with Conditional Statements

You can use conditional statements within for loops to filter or transform data based on certain criteria. This is especially helpful when different actions are needed based on the data you're handling.

// Basic conditional statement
const numbers = [1, 2, 3, 4, 5];
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] % 2 === 0) {
console.log(`Even number: ${numbers[i]}`);
} else {
console.log(`Odd number: ${numbers[i]}`);
}
}

// Using a for...of loop with a conditional statement
for (const number of numbers) {
if (number % 2 === 0) {
console.log(`Even number: ${number}`);
} else {
console.log(`Odd number: ${number}`);
}
}

While array methods like filter() and map() can accomplish similar tasks, using for loops with conditionals gives you more control over the iteration process and can be more readable for complex logic. For examples of combining loops with filters in a database context, check out Convex's guide on complex filters.

Handling Asynchronous Operations inside For Loops

Combining asynchronous operations with loops requires special attention in TypeScript. You'll often need this when working with APIs or databases like in the Convex data fetching patterns:

// Using async/await with a for loop
async function fetchNumbers() {
const numbers = [1, 2, 3, 4, 5];
for (const number of numbers) {
const response = await fetch(`https://example.com/${number}`);
const data = await response.json();
console.log(data);
}
}

// Using Promise.all with a for loop
function fetchNumbers() {
const numbers = [1, 2, 3, 4, 5];
const promises = numbers.map((number) => fetch(`https://example.com/${number}`));
Promise.all(promises).then((responses) => {
responses.forEach((response) => {
response.json().then((data) => console.log(data));
});
});
}

The async/await approach processes items sequentially, while Promise<T> handles them in parallel. For database operations, you might want to check out Convex's TypeScript-first query patterns to handle data fetching efficiently.

Improving Performance with For Loops

When processing large datasets in TypeScript, optimizing your array loops can significantly improve performance. Here are some proven techniques:

// Using a for...of loop with a large array
const largeArray = new Array(1000000).fill(0);
for (const value of largeArray) {
// Perform some operation
}

// Using a for loop with a large array and caching results
const largeArray = new Array(1000000).fill(0);
const cache = {};
for (let i = 0; i < largeArray.length; i++) {
if (cache[i]) {
// Use cached result
} else {
const result = performSomeOperation(largeArray[i]);
cache[i] = result;
}
}

// Breaking early from a for loop
const largeArray = new Array(1000000).fill(0);
for (const value of largeArray) {
if (someCondition) {
break;
}
// Perform some operation
}

Each approach has its place: caching helps avoid repeated calculations, while breaking early can prevent unnecessary iterations. When working with databases, you can find more optimization strategies in Convex's performance best practices.

Final Thoughts on TypeScript For Loops

For loops are essential for data processing in TypeScript. By choosing the right loop type and applying these patterns, you can write cleaner, more efficient code. Ready to test these concepts? Try them out in the typescript playground.