Typing Arrays and Objects
Describe collections and structured values, the two shapes almost all data takes.
What you'll learn
- Type an array so its elements are checked
- Describe an object's shape inline
- Explain why an excess property is rejected in an object literal
Prerequisites
Explanation
Real data is rarely a lone string. It is a list of things, or a thing with fields — usually both.
Arrays
Write the element type followed by []:
const scores: number[] = [90, 78, 100];
const names: string[] = ["Ada", "Grace"];
Every element is now checked, and so is everything you push later. scores.push("100") is rejected. The payoff shows up in the methods: because TypeScript knows scores holds numbers, it knows scores.map(s => s * 2) is valid and that the result is number[], while scores.map(s => s.toUpperCase()) is not.
An empty array with no annotation is a trap. const items = [] infers any[] — a list that accepts anything. Annotate empty arrays.
Objects
Describe the shape inline, field by field:
const lesson: { title: string; minutes: number } = {
title: "Typing Arrays",
minutes: 22,
};
Missing a field is an error. Getting a field's type wrong is an error. And so is adding a field that is not in the shape — this one catches people out:
const lesson: { title: string } = { title: "Intro", minutes: 22 };
// ^^^^^^^ rejected
That is the excess property check. TypeScript's reasoning: you wrote this literal here, in a place with a declared shape, so an extra property is almost certainly a typo or a misunderstanding rather than an intention. It is a deliberate strictness that only applies to object literals assigned directly to a typed target.
Nesting
Shapes compose, and arrays of objects are the everyday case:
const modules: { id: string; lessons: string[] }[] = [
{ id: "basics", lessons: ["a", "b"] },
];
Note the trailing [] — that is "array of that shape". Inline shapes get unreadable fast at this size, which is exactly the problem the next lesson solves with named types.
Example
An array of typed objects, and the methods that stay type-safe over it.
const lessons: { title: string; minutes: number }[] = [
{ title: "Why Types", minutes: 18 },
{ title: "Inference", minutes: 20 },
{ title: "Arrays and Objects", minutes: 22 },
];
const totalMinutes = lessons.reduce((sum, l) => sum + l.minutes, 0);
const titles = lessons.map((l) => l.title);
console.log(totalMinutes);
console.log(titles.join(" | "));Try it yourself
Add a fourth lesson. Then try adding a property that is not in the shape, and read the error.
Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.
Guided exercise
Guided exercise
Declare `temperatures` as a `number[]` holding 12, 15, and 9. Then create `warmDays` containing only the values above 10, and log its length.
Checks: temperatures holds 3 numbers · warmDays holds 2 values · plus 1 hidden check
Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.
Stuck? Get a hint.
Independent exercise
Independent exercise
Declare `student` as an object typed inline with `name` (string) and `grades` (number[]). Then write `average(): number` that returns the mean of `student.grades`. With grades [80, 90, 100] the average is 90.
Checks: student has a string name · student.grades holds 3 numbers · average() returns 90
Code editor. Press Escape then Tab to leave the editor if keyboard focus becomes trapped. Press Control+Shift+M inside the editor to toggle Tab-key focus trapping.
Stuck? Get a hint.
Common mistakes
- Leaving an empty array unannotated. `const items = []` infers `any[]`, which quietly accepts anything you push later.
- Being surprised that an extra property is rejected. The excess property check is deliberate, and it applies to object literals assigned to a declared shape.
- Writing `Array<number>` and `number[]` as though they differ. They are the same type in two syntaxes.
Knowledge check
Takeaway
`type[]` checks every element; an inline `{ field: type }` checks every field — including rejecting fields you did not declare.
Summary
Arrays are typed with a trailing `[]`, objects with an inline field list. Empty arrays need annotations, and object literals assigned to a declared shape are rejected if they carry extra properties.
References
Your notes
Notes save automatically.
Finished this lesson?
Mark it complete to track your progress and schedule a future review.
AI tutor
The optional AI tutor isn't enabled in this deployment. All lessons, exercises, quizzes, and search work fully without it.