Typescript Iterate Over Records

Recently, I was working on a TypeScript project where I had to iterate through a Record object that stored user information with unique IDs.

The issue is that there are multiple ways to iterate over a record in TypeScript, and each method has its own advantages and disadvantages.

In this article, I will cover five effective ways to iterate over Records in TypeScript, with practical examples that you can start using right away. So let’s dive in!

What is a Record Type in TypeScript?

Before we jump into iteration methods, let’s understand what a Record is in TypeScript. A Record is a utility type that defines an object type with specific key and value types. It’s like a map where you can strictly define what types your keys and values should be.

Here’s a basic example:

// Record<string, number> means keys are strings and values are numbers
const userScores: Record<string, number> = {
  'john': 85,
  'sarah': 92,
  'mike': 78
};

Now, let’s explore how to iterate over this kind of structure.

Check out: Iterate Over Objects in TypeScript

Typescript Iterate Over Records: Different Methods

Below, I will explain the different methods for iterating over records in TypeScript.

Method 1 – Using Object.entries() in TypeScript

The most modern and my favorite way to iterate over a Record is using Object.entries(). This method returns an array of key-value pairs, which you can then destructure in a loop.

const userProfiles: Record<string, {age: number, state: string}> = {
  'user1': {age: 28, state: 'California'},
  'user2': {age: 34, state: 'Texas'},
  'user3': {age: 42, state: 'New York'}
};

// Iterating using Object.entries()
for (const [userId, profile] of Object.entries(userProfiles)) {
  console.log(`${userId} is ${profile.age} years old and lives in ${profile.state}`);
}

What I love about this approach is its clean and readable design. The destructuring syntax makes it immediately clear what data you’re working with.

Typescript Iterate Over Records

Method 2 – Using Object.keys() with Index Access in TypeScript

Another common approach is to use Object.keys() and then access the values using the keys.

const stateCapitals: Record<string, string> = {
  'California': 'Sacramento',
  'Texas': 'Austin',
  'Florida': 'Tallahassee',
  'New York': 'Albany'
};

// Iterating using Object.keys()
Object.keys(stateCapitals).forEach(state => {
  console.log(`The capital of ${state} is ${stateCapitals[state]}`);
});

This method provides access to the keys first, which can be useful when you’re primarily interested in the keys or need to perform some filtering based on them.

Use Object.keys() with Index Access in TypeScript

Check out: Index Signature in TypeScript

Method 3 – Using Object.values() in TypeScript

If you’re only interested in the values and don’t need the keys, Object.values() is the way to go.

const populationByCity: Record<string, number> = {
  'New York': 8419000,
  'Los Angeles': 3980000,
  'Chicago': 2716000,
  'Houston': 2328000
};

// Iterating using Object.values()
let totalPopulation = 0;
Object.values(populationByCity).forEach(population => {
  totalPopulation += population;
});

console.log(`Total population: ${totalPopulation}`);

This method is ideal for calculations or operations that only require the values, such as summing or finding maximums.

Use Object.values() in TypeScript

Method 4 – Using for…in Loop in TypeScript

The classic for…in loop is still a valid option, especially when working with older codebases or environments.

const companyStocks: Record<string, {price: number, change: number}> = {
  'AAPL': {price: 145.86, change: 0.41},
  'GOOGL': {price: 2750.01, change: -1.23},
  'AMZN': {price: 3379.09, change: 2.17},
  'MSFT': {price: 280.75, change: 1.09}
};

// Iterating using for...in
for (const ticker in companyStocks) {
  const {price, change} = companyStocks[ticker];
  const status = change >= 0 ? 'up' : 'down';
  console.log(`${ticker} is trading at $${price} and is ${status} by ${Math.abs(change)}%`);
}

One thing to be careful about with for…in is that it will iterate over all enumerable properties, including those inherited through the prototype chain. This is rarely an issue with simple Record objects, but it’s something to be aware of.

Use for-in Loop in TypeScript

Check out: Deep Clone an Object in TypeScript

Method 5 – Using forEach with TypeScript’s Mapped Types

For more complex scenarios, you can combine TypeScript’s mapped types with forEach:

type StateInfo = {
  capital: string;
  population: number;
  established: number;
};

const statesData: Record<string, StateInfo> = {
  'California': {
    capital: 'Sacramento',
    population: 39510000,
    established: 1850
  },
  'Texas': {
    capital: 'Austin',
    population: 29000000,
    established: 1845
  },
  'Florida': {
    capital: 'Tallahassee',
    population: 21480000,
    established: 1845
  }
};

// Creating a mapped type helper function
function forEachEntry<K extends string | number | symbol, V>(
  record: Record<K, V>,
  callback: (key: K, value: V, index: number) => void
): void {
  Object.entries(record).forEach(([key, value], index) => {
    callback(key as K, value as V, index);
  });
}

// Using our helper function
forEachEntry(statesData, (state, info, index) => {
  console.log(`[${index}] ${state} was established in ${info.established} and has a population of ${info.population}`);
});

This approach is more verbose but provides complete type safety and the flexibility to create reusable iteration utilities tailored to your specific needs.

Use forEach with TypeScript&#039;s Mapped Types

Type-Safe Iteration with Generic Constraints in TypeScript

When working with complex TypeScript projects, you might want more type safety during iteration. Here’s how you can create a type-safe iteration utility:

function iterateRecord<K extends string | number | symbol, V>(
  record: Record<K, V>,
  callback: (key: K, value: V) => void
): void {
  (Object.entries(record) as [K, V][]).forEach(
    ([key, value]) => callback(key, value)
  );
}

// Using the type-safe utility
const salesData: Record<string, {q1: number, q2: number, q3: number, q4: number}> = {
  'Electronics': {q1: 50000, q2: 45000, q3: 55000, q4: 75000},
  'Clothing': {q1: 30000, q2: 35000, q3: 28000, q4: 42000},
  'Food': {q1: 25000, q2: 28000, q3: 30000, q4: 32000}
};

iterateRecord(salesData, (department, quarterly) => {
  const yearlyTotal = quarterly.q1 + quarterly.q2 + quarterly.q3 + quarterly.q4;
  console.log(`${department} had total yearly sales of $${yearlyTotal}`);
});

Check out: Use Typescript Omit with Multiple Properties

Type-Safe Iteration with Generic Constraints in TypeScript

Conclusion

I hope you found this article helpful. Each method for iterating over a Record in TypeScript has its place, and choosing the right one depends on your specific needs:

  • Use Object.entries() for the clearest, most modern syntax
  • Choose Object.keys() when you need to work primarily with keys
  • Opt for Object.values() when you only care about the values
  • Consider for…in for compatibility with older code
  • Create custom utility functions for complex, type-safe iterations

Remember that TypeScript’s Record type is a powerful way to enforce type safety on your objects, and combining it with these iteration methods gives you both flexibility and compile-time checking.

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.