Why dictionaries have no length
An array has a length property, but a plain object does not. Reading scores.length on a dictionary gives undefined, and with a Record<string, number> type the compiler even accepts it, so the mistake shows up only in the output. To count the pairs in an object, first turn its keys into an array, then take that array's length.
const scores: Record<string, number> = {"Alice": 95, "Bob": 87, "Charlie": 72};
let count: number = Object.keys(scores).length;
console.log(count); // 3
The method Object.keys(scores) returns an array of the object's own keys: ["Alice", "Bob", "Charlie"]. The .length that follows is the ordinary array length, and it equals the number of pairs.
Other ways to count
The values and the entries have the same count as the keys, because each pair has exactly one of each:
const d: Record<string, number> = {"a": 1, "b": 2};
console.log(Object.keys(d).length); // 2
console.log(Object.values(d).length); // 2
console.log(Object.entries(d).length); // 2
All three build a temporary array, so counting is proportional to the number of pairs. That is fine for the sizes in these lessons. Use Object.keys, which is the clearest way to say "how many keys".
A Map works differently: it has a size property, with no parentheses and no temporary array.
const m = new Map<string, number>([["a", 1], ["b", 2]]);
console.log(m.size); // 2
What the count reflects
The length of the keys array always matches the current state of the object, so the count changes as pairs come and go:
const scores: Record<string, number> = {"Alice": 95, "Bob": 87};
scores["Charlie"] = 72;
console.log(Object.keys(scores).length); // 3
scores["Alice"] = 99; // updates, adds nothing
console.log(Object.keys(scores).length); // 3
delete scores["Bob"];
console.log(Object.keys(scores).length); // 2
Adding a new key raises the count by one, updating an existing key leaves it the same, and delete lowers it. Setting a key to undefined does not lower it: the key remains and is still counted.
The count is also not remembered. Each Object.keys(scores).length makes a new array, so storing the result in count gives a snapshot. If the dictionary changes afterwards, count still holds the old number.
Why it returns an array
Returning an array is not only about the length. Because the result is an ordinary array, you can loop over it with for...of, sort it, or filter it. A dictionary can't be looped with for...of directly, so Object.keys is also the standard way to walk through the pairs. The length is simply the quickest thing to ask of that array.
Using the count
The key count is useful on its own and as a building block. To test whether a dictionary is empty, compare it with zero:
const empty: Record<string, number> = {};
console.log(Object.keys(empty).length === 0); // true
To count only the pairs that meet a condition, take the values, filter them, and measure the result. To average the values, divide their sum by the key count:
const scores: Record<string, number> = {"Alice": 95, "Bob": 87, "Charlie": 72};
const passed = Object.values(scores).filter((s) => s >= 80).length;
console.log(passed); // 2
const total = Object.values(scores).reduce((a, b) => a + b, 0);
console.log(total / Object.keys(scores).length); // 84.66666666666667
Dividing by the count of an empty dictionary gives NaN (zero divided by zero), so check for emptiness first when that can happen.
The lesson's exercise
The starting code declares scores with three entries. The one step is to count them and store the count in a variable.
- Get the keys.
Object.keys(scores)returns the array of keys. - Take the length. Adding
.lengthgives the number of keys. - Store it. Declare
countwithlet, give it the typenumber, and assign the expression.
const scores: Record<string, number> = {"Alice": 95, "Bob": 87, "Charlie": 72};
let count: number = Object.keys(scores).length;
Here count is 3. The word length has no parentheses, because it is a property of the array, not a method.
Gotchas
scores.lengthis not the count. It isundefinedon a dictionary.Object.keysis a function, not a method of the object. WriteObject.keys(scores), notscores.keys(), which fails at run time because a plain object has nokeysmethod.- An empty dictionary has count 0.
Object.keys({}).lengthis0. - Only the object's own keys are counted. Names inherited by every object, like
toString, are not included.
Key takeaways
- Count the pairs of an object with
Object.keys(obj).length. Object.values(obj).lengthgives the same number.- A
Mapuses itssizeproperty instead. - The result is a snapshot of the dictionary at that moment.