beginner22 min

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.

Loading editor…

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.

Loading editor…

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.

Loading editor…

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

Knowledge check

1. What does TypeScript infer for `const items = []`?
2. Given `const u: { name: string } = { name: "Ada", age: 30 };`, what happens?
3. How do you type an array of objects that each have a `title` string?

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.