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.

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.

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.

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.

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.

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

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.

I am Bijay Kumar, a Microsoft MVP in SharePoint. Apart from SharePoint, I started working on Python, Machine learning, and artificial intelligence for the last 5 years. During this time I got expertise in various Python libraries also like Tkinter, Pandas, NumPy, Turtle, Django, Matplotlib, Tensorflow, Scipy, Scikit-Learn, etc… for various clients in the United States, Canada, the United Kingdom, Australia, New Zealand, etc. Check out my profile.