To get the first element from a TypeScript dictionary, read index 0 of Object.entries() for a plain object or Record, and call .entries().next().value for a Map. Both give back undefined when the dictionary is empty:
const [state, amount] = Object.entries(salesByState)[0]; // Record / object
const first = ordersByZip.entries().next().value; // Map
I ran all five examples with TypeScript 7.0.2 and Node.js v22.22.2 (strict mode on), so the outputs you see are real console text, not guesses.
“First” isn’t always the key you added first, though. Below you’ll see the object version, the key-order rule that surprises people, the Map version, and how to stop an empty dictionary from crashing your code.
Get the first element from a TypeScript dictionary (Record)
A dictionary in TypeScript is usually a Record<string, V>. Pick the helper that matches what you need: Object.keys() for the key, Object.values() for the value, or Object.entries() for both as a [key, value] pair:
const salesByState: Record<string, number> = {
Texas: 18450.75,
California: 22310.4,
Florida: 15980,
Ohio: 9125.5,
};
const firstKey = Object.keys(salesByState)[0];
const firstValue = Object.values(salesByState)[0];
const [state, amount] = Object.entries(salesByState)[0];
console.log("first key: ", firstKey);
console.log("first value:", firstValue.toFixed(2));
console.log(`first entry: ${state} -> $${amount.toFixed(2)}`);
const empty: Record<string, number> = {};
console.log("empty keys[0]: ", Object.keys(empty)[0]);
console.log("empty entries[0]:", Object.entries(empty)[0]);
try {
console.log(Object.keys(empty)[0].toUpperCase()); // compiles under --strict
} catch (err) {
console.log("runtime:", (err as Error).message);
}
Output:
first key: Texas
first value: 18450.75
first entry: Texas -> $18450.75
empty keys[0]: undefined
empty entries[0]: undefined
runtime: Cannot read properties of undefined (reading 'toUpperCase')

undefined or a runtime TypeError.The last line matters most: plain --strict types Object.keys(empty)[0] as string, so the call compiles and then crashes. I’ll fix that below. If you’re new to Record, start with TypeScript Record explained.
Object.entries() is my default because destructuring gives you both halves at once. For more on working with pairs, read key-value pairs in TypeScript.
Which key comes first in a TypeScript object?
Objects don’t keep pure insertion order. Keys that look like array indexes (“0”, “1”, “10001”) always come first in ascending numeric order. Other string keys follow in the order you added them:
const cityByZip: Record<string, string> = {
"90210": "Beverly Hills, CA",
"10001": "New York, NY",
"60601": "Chicago, IL",
};
console.log("keys: ", Object.keys(cityByZip));
console.log("first:", Object.entries(cityByZip)[0]);
const mixed: Record<string, number> = { b: 1, "2": 2, a: 3, "1": 4, "-1": 5, "01": 6, "1.5": 7 };
console.log("mixed:", Object.keys(mixed));
const prefixed: Record<string, string> = {
"zip-90210": "Beverly Hills, CA",
"zip-10001": "New York, NY",
};
console.log("prefixed first:", Object.keys(prefixed)[0]);
Output:
keys: [ '10001', '60601', '90210' ]
first: [ '10001', 'New York, NY' ]
mixed: [
'1', '2',
'b', 'a',
'-1', '01',
'1.5'
]
prefixed first: zip-90210

Notice that “-1”, “01” and “1.5” stay in insertion order. They aren’t canonical array indexes, so only plain non-negative integers get moved to the front.
If your keys are IDs or ZIP codes, prefix them (“zip-90210”) or switch to a Map. The same order applies to for...in and every helper in iterating over objects in TypeScript.
Get the first element from a TypeScript Map
A Map keeps pure insertion order for every key type, so its first entry really is the first one you added. Its keys(), values() and entries() methods return iterators, and next() reads one item without copying the rest:
const ordersByZip = new Map<string, number>([
["90210", 249.99],
["10001", 89.5],
["60601", 120],
]);
const firstKey = ordersByZip.keys().next().value; // string | undefined
const firstEntry = ordersByZip.entries().next().value; // [string, number] | undefined
console.log("first key: ", firstKey);
console.log("first entry:", firstEntry);
const [[zip, total]] = ordersByZip; // destructure the first entry
console.log(`destructured: ${zip} -> $${total.toFixed(2)}`);
ordersByZip.set("90210", 260); // update keeps its position
ordersByZip.delete("10001");
ordersByZip.set("10001", 89.5); // re-adding moves it to the end
console.log("order now: ", [...ordersByZip.keys()]);
const empty = new Map<string, number>();
console.log("empty next():", empty.entries().next());
const [nothing] = empty;
console.log("empty [first]:", nothing);
try {
const [[k]] = empty;
console.log(k);
} catch (err) {
console.log("empty [[k]]:", (err as Error).message);
}
Output:
first key: 90210
first entry: [ '90210', 249.99 ]
destructured: 90210 -> $249.99
order now: [ '90210', '60601', '10001' ]
empty next(): { value: undefined, done: true }
empty [first]: undefined
empty [[k]]: undefined is not iterable (cannot read property Symbol(Symbol.iterator))

{ value: undefined, done: true }.Updating an existing key keeps its spot, while deleting and re-adding moves it to the end. On an empty Map, const [first] = map is safe, but nested destructuring like [[k]] throws.
With --strict, next().value is typed string | undefined, so TypeScript makes you check it. Building the Map is covered in how to initialize a Map in TypeScript, and converting a Map to an array helps when you need more than the first item.
How do I handle an empty dictionary safely?
Turn on noUncheckedIndexedAccess in tsconfig.json (or pass the flag). Index access then returns V | undefined, and the code that crashed earlier stops compiling:
const salesByState: Record<string, number> = {};
const firstState = Object.keys(salesByState)[0];
console.log(firstState.toUpperCase());
const [, firstAmount] = Object.entries(salesByState)[0];
console.log(firstAmount.toFixed(2));
Output:
dict_unchecked.ts(4,13): error TS18048: 'firstState' is possibly 'undefined'.
dict_unchecked.ts(6,7): error TS2488: Type '[string, number] | undefined' must have a '[Symbol.iterator]()' method that returns an iterator.

TS18048 flags the key, and TS2488 means you can’t destructure an entry that might not exist. The fix is a small helper with an honest return type, so you handle undefined once. This file compiles cleanly with the flag on:
function firstEntry<V>(dict: Record<string, V>): [string, V] | undefined {
return Object.entries(dict)[0];
}
function firstKey(dict: object): string | undefined {
for (const key in dict) {
if (Object.hasOwn(dict, key)) return key; // stops at the first own key
}
return undefined;
}
const sales: Record<string, number> = { Texas: 18450.75, Ohio: 9125.5 };
const none: Record<string, number> = {};
const entry = firstEntry(sales);
if (entry) {
const [state, amount] = entry;
console.log(`first: ${state} $${amount.toFixed(2)}`);
}
console.log("empty:", firstEntry(none) ?? "no entries");
console.log("firstKey:", firstKey(sales), "|", firstKey(none) ?? "none");
console.log("label:", Object.keys(none)[0]?.toUpperCase() ?? "N/A");
Output:
first: Texas $18450.75
empty: no entries
firstKey: Texas | none
label: N/A
The for...in version returns at the first own key, so it doesn’t build an array of every key. For other ways to guard values, see checking if an object is undefined in TypeScript and checking whether a key exists.
Record vs Map for the first element
| Need | Record / object | Map |
|---|---|---|
| First key | Object.keys(d)[0] | m.keys().next().value |
| First pair | Object.entries(d)[0] | m.entries().next().value |
| Order | Integer-like keys first, then insertion | Always insertion order |
| Empty result | undefined (typed only with the flag) | undefined (typed in strict mode) |
If the order of keys matters, I reach for a Map. When your data starts as an array, convert an array to a dictionary or create a Map from an array first.
Here are a few more dictionary and Map guides worth a look:
Frequently asked questions
How do I get the first key of a dictionary in TypeScript?
Use Object.keys(dict)[0] for an object or map.keys().next().value for a Map. Both return undefined when it’s empty.
Why isn’t the first key the one I added first?
Objects list integer-like keys such as “10001” first in ascending order. Prefix those keys or use a Map, which keeps insertion order.
How do I get the first value of a Map?
Call map.values().next().value, or destructure with const [first] = map.values();.
Why doesn’t TypeScript warn that keys[0] may be undefined?
Index access on arrays and records isn’t checked by default. Enable noUncheckedIndexedAccess so it’s typed as possibly undefined.
Why does Object.keys return string[] and not keyof T?
Objects can carry extra properties at runtime, so TypeScript can’t promise only known keys. Cast only when you control the object.
Where is Map’s insertion order documented?
See Map on MDN.

Bijay Kumar is a 13-time Microsoft MVP with more than 18 years in software development, and the founder of Python Guides and TSinfo Technologies. He started out building .NET and SharePoint solutions at HP, TCS and KPIT before moving into Python, machine learning and AI, and he also builds web apps with TypeScript and React. He writes the tutorials here himself, and every example is run before publishing so you see the real output. More about Bijay · Microsoft MVP profile · LinkedIn