How to Convert an Object to an Array in TypeScript

To convert an object to an array in TypeScript, use Object.values(obj) for the values, Object.keys(obj) for the property names, or Object.entries(obj) for [key, value] pairs. Each returns a new array and leaves the object alone:

const counts = Object.values(inventory);   // number[]
const pairs = Object.entries(inventory);   // [string, number][]

These examples were compiled with –strict and run with TypeScript 7.0.2 on Node.js v22.22.2; nothing below is hand-typed output.

You’ll see the three built-in methods and the types they return, the Object.keys indexing error, turning a dictionary of records into an array of objects, and the key-order surprises to know about.

Convert an object to an array with Object.keys, values and entries

All three walk the object’s own enumerable properties in the same order, so index 0 of each array lines up:

const inventory = { austin: 120, denver: 85, seattle: 42 };

const cities: string[] = Object.keys(inventory);
const counts: number[] = Object.values(inventory);
const pairs: [string, number][] = Object.entries(inventory);

console.log(cities);
console.log(counts);
console.log(pairs);
console.log("total units:", counts.reduce((a, b) => a + b, 0));

Output:

[ 'austin', 'denver', 'seattle' ]
[ 120, 85, 42 ]
[ [ 'austin', 120 ], [ 'denver', 85 ], [ 'seattle', 42 ] ]
total units: 247
Command Prompt output of TypeScript Object.keys, Object.values and Object.entries converting an inventory object to arrays
The city names, the unit counts and the key-value pairs print as three arrays, followed by the total units.

Once you have an array, every array method works on it. For example, totals use the same approach as summing an array in TypeScript.

Why does Object.keys return string[] instead of keyof?

This is the error people hit first. Object.keys() is typed as string[] on purpose, since an object can hold more properties than its type lists. So indexing with those keys fails in strict mode:

const prices = { coffee: 4.5, bagel: 3.25, juice: 5.75 };

for (const item of Object.keys(prices)) {
  console.log(item, prices[item]);
}

Output:

obj_keys_error.ts(4,21): error TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ coffee: number; bagel: number; juice: number; }'.
  No index signature with a parameter of type 'string' was found on type '{ coffee: number; bagel: number; juice: number; }'.
Command Prompt showing TypeScript error TS7053 element implicitly has an any type when indexing an object with Object.keys
The compiler stops with TS7053 because a plain string can’t index the prices object.

Two fixes: cast the keys when you know the object is exactly that shape, or use Object.entries(), which hands you the value directly:

const prices = { coffee: 4.5, bagel: 3.25, juice: 5.75 };
type Item = keyof typeof prices;

const items = Object.keys(prices) as Item[];
for (const item of items) {
  console.log(item.padEnd(7), `$${prices[item].toFixed(2)}`);
}

for (const [item, price] of Object.entries(prices)) {   // no cast needed
  console.log(`${item}: $${price.toFixed(2)}`);
}

Output:

coffee  $4.50
bagel   $3.25
juice   $5.75
coffee: $4.50
bagel: $3.25
juice: $5.75

I reach for entries() first since it needs no cast. More ways to walk an object’s properties are in iterating over objects in TypeScript.

Convert an object of objects to an array of objects

APIs often return records keyed by ID. To sort, filter or show them in a table, turn each entry into one object that keeps its key as a property:

interface Store {
  city: string;
  state: string;
  revenue: number;
}

const stores: Record<string, Store> = {
  s101: { city: "Austin", state: "TX", revenue: 18250.5 },
  s102: { city: "Denver", state: "CO", revenue: 12990.0 },
  s103: { city: "Tampa", state: "FL", revenue: 15420.75 },
};

const rows = Object.entries(stores).map(([id, store]) => ({ id, ...store }));
console.table(rows);

const best = rows.toSorted((a, b) => b.revenue - a.revenue)[0];
console.log(`Top store: ${best.id} in ${best.city}, $${best.revenue.toFixed(2)}`);

const back = Object.fromEntries(rows.map(({ id, ...rest }) => [id, rest]));
console.log(Object.keys(back));

Output:

┌─────────┬────────┬──────────┬───────┬──────────┐
│ (index) │ id     │ city     │ state │ revenue  │
├─────────┼────────┼──────────┼───────┼──────────┤
│ 0       │ 's101' │ 'Austin' │ 'TX'  │ 18250.5  │
│ 1       │ 's102' │ 'Denver' │ 'CO'  │ 12990    │
│ 2       │ 's103' │ 'Tampa'  │ 'FL'  │ 15420.75 │
└─────────┴────────┴──────────┴───────┴──────────┘
Top store: s101 in Austin, $18250.50
[ 's101', 's102', 's103' ]
Command Prompt console.table of TypeScript store records converted from an object to an array of objects with Object.entries and map
console.table shows each store with its ID, city, state and revenue; Austin comes out as the top store.

Object.fromEntries() reverses the trip. If your data is in a Map rather than a plain object, use converting a Map to an array instead.

Object key order and class instances

Arrays from these methods follow JavaScript’s property order: integer-like keys come first in numeric order, then the other keys in insertion order. Class getters and methods live on the prototype, so they’re skipped:

const zips = { "90210": "Beverly Hills", "02134": "Boston", "10001": "New York", main: "HQ" };
console.log(Object.keys(zips));

class Customer {
  constructor(public name: string, public spent: number) {}
  get vip(): boolean { return this.spent > 1000; }
  greet(): string { return `Hi ${this.name}`; }
}
const c = new Customer("Emily", 1250);
console.log(Object.entries(c));
console.log("vip" in c, c.vip);

Output:

[ '10001', '90210', '02134', 'main' ]
[ [ 'name', 'Emily' ], [ 'spent', 1250 ] ]
true true
Command Prompt output of TypeScript Object.keys sorting integer-like ZIP keys first and Object.entries skipping class getters
The ZIP 10001 and 90210 keys move to the front while 02134 keeps its place, and the class instance gives only name and spent.

"02134" isn’t integer-like because of its leading zero, so it stays in insertion order. If key order matters, store the data as an array or a Map. For typed dictionaries in general, see TypeScript Record explained.

Object to array methods compared

MethodReturnsUse it for
Object.keys(o)string[]Property names
Object.values(o)T[]Just the values
Object.entries(o)[string, T][]Keys and values together
entries().map(([id, v]) => ({ id, ...v }))Array of objectsTables, sorting, filtering
Object.fromEntries(arr)ObjectConverting back

After the conversion, you’ll often want a single record back out, such as one store by ID. That’s covered in finding an object in a TypeScript array.

If you’re reshaping data in TypeScript, these guides help too:

Frequently asked questions

How do I convert an object to an array in TypeScript?

Use Object.values() for values, Object.keys() for keys, or Object.entries() for key-value pairs.

Why is Object.keys typed as string[]?

TypeScript types are open, so an object may carry extra properties at runtime. Cast with as (keyof T)[] only when you’re sure of the shape.

How do I keep the key when converting an object of objects?

Use Object.entries(obj).map(([id, v]) => ({ id, ...v })).

How do I convert the array back to an object?

Use Object.fromEntries() with an array of [key, value] pairs.

Why are my numeric keys in a different order?

Integer-like keys always come first in ascending order. Use a Map or an array when order matters.

Where is Object.entries documented?

See Object.entries() on MDN.