Skip to content

Exercise 9 of 10 · Object types

The Departure Board

What you will make

A station departure board showing the destination, platform and wait for every train, built from objects that all match one Train type.

The one new idea: an object type lists the properties an object must have, and the compiler checks every object against it

Real data comes in records: a customer with a name and an email, an order with items and a total, a train with a destination and a platform. An object type writes the shape of a record down once, and from then on the compiler refuses any record with a piece missing, misspelt or of the wrong kind.

Go straight to the code ↓

A train on a departure board is not one value but several that belong together: where it goes, which platform, how long until it leaves. An object holds them as named properties:

TypeScript
const ferry = { destination: "Skye", cars: 32 };

console.log(ferry.destination);
console.log(ferry.cars + 1);
Output
Skye
33

Curly braces make the object. Inside them, each property is a name, a colon and a value, with commas between the properties. A dot reads a property back out, so ferry.destination is "Skye".

A type describes the shape

An object type writes that shape down and gives it a name:

TypeScript
type Ferry = {
  destination: string;
  cars: number;
};

const morning: Ferry = { destination: "Skye", cars: 32 };

console.log(morning.destination, "with", morning.cars, "cars");
Output
Skye with 32 cars

type Ferry = { ... }; makes a new type called Ferry. Each line inside it lists one property: its name, a colon, its type and a semicolon. The type prints nothing and creates no ferry. It is a description the compiler holds objects to, and const morning: Ferry is a type annotation like : number, promising that morning has that shape.

Type names start with a capital letter by habit, which keeps Ferry, the description, apart from morning, an actual ferry.

What the compiler checks

Leave a property out:

TypeScript
type Ferry = {
  destination: string;
  cars: number;
};

const evening: Ferry = { destination: "Mull" };

console.log(evening.destination);
Output
main.ts(6,7): error TS2741: Property 'cars' is missing in type '{ destination: string; }' but required in type 'Ferry'.

The part in the middle, { destination: string; }, is the compiler describing the object you actually wrote. It sets that against Ferry, the shape you promised, and cars is the difference.

Misspell a property, and the compiler suggests the one you meant:

TypeScript
type Ferry = {
  destination: string;
  cars: number;
};

const evening: Ferry = { destination: "Mull", crs: 12 };

console.log(evening.destination);
Output
main.ts(6,47): error TS2561: Object literal may only specify known properties, but 'crs' does not exist in type 'Ferry'. Did you mean to write 'cars'?

An object literal is an object written out in braces, like the one on that line.

An array of objects

Train[] is an array of trains, the way string[] was an array of strings. Every object in it is checked against Train, and a for...of loop hands them over one at a time already known to be trains, which is why each one can be handed to departure, whose parameter says it takes a Train.

Your turn

The editor holds a departure board: a Train type, a departure function that builds one row from a train, and three trains in an array. Press Run first. Nothing prints, and the compiler reports:

Output
main.ts(20,3): error TS2741: Property 'platform' is missing in type '{ destination: string; minutes: number; }' but required in type 'Train'.

Line 20 is the Dover train. Give it the property it is missing; the comment at the top of the program says which platform Dover leaves from.

If something goes wrong

If the message changes to Type 'string' is not assignable to type 'number'., the platform has quotes around it. A platform here is a number, as the type says.

If the compiler asks Did you mean to write 'platform'?, the property name is misspelt. Property names must match the type letter for letter.

If you deleted platform from the type instead, several new messages arrive at once: the other two trains still have a platform the type no longer knows about, and the departure function still reads train.platform. The type describes what a train is. Fix the data to fit it, not the other way round.

Write your code

Runs in your browser. Press Run (or Ctrl/Cmd+Enter) and the output is checked for you.

Ctrl/Cmd+Enter to run

Press Esc then Tab to move keyboard focus out of the code editor.

Ready
Output will appear here after you run your code.

The runtime is starting in the background. You can type now — it will be ready before you are.

The answer appears here once you have run your code at least once.

Things that often go wrong here

Giving the platform in quotes
The Train type says a platform is a number, and quotes make text, so the compiler refuses the Dover line with Type 'string' is not assignable to type 'number'. Take the quotes off the 2.
Misspelling the new property
Property names must match the type letter for letter. Written as platfrom, the compiler both refuses the unknown name and suggests the right one: Object literal may only specify known properties, but 'platfrom' does not exist in type 'Train'. Did you mean to write 'platform'?
Deleting platform from the type instead of adding it to Dover
The first message goes and new ones take its place: the other two trains still have a platform the type no longer knows about, and the departure function still reads train.platform, which now gives Property 'platform' does not exist on type 'Train'. The type describes what a train is; change the data to fit it.
Writing an equals sign inside the object
Inside the braces of an object, each property is a name, a colon and a value. With platform = 2 the compiler stops and asks whether you meant a colon, before anything prints.

Want a blank editor instead? Open the TypeScript playground.