Skip to content
Theory · Object types · lesson 1 of 7

Object types

What you'll learn

What you'll learn:

  • describe an object's shape with a type such as { name: string; age: number };
  • name a type with type and read errors about a missing property;
  • declare optional properties and check them before use;
  • forbid writes to a property with readonly and know where that protection ends.
A form with the fields name, an optional age? in a dashed box, and a printed id with a padlock

Picture a paper form. Its fields are printed in advance: "Name", "Age". The clerk who takes the form checks two things: whether every field is filled in and whether it holds the right kind of answer. If the "Age" field holds a word rather than a number, the form comes back for correction.

JavaScript has no such check. A function receives an object and hopes it has the properties it needs. If a property is missing, the function silently gets undefined, and the bug surfaces later, far from where it was made.

In TypeScript an object has its own form, an object type: a list of property names and the type of each. The compiler checks every object you pass against it:

TypeScript
function describe(user: { name: string; age: number }) {
    return `${user.name}, ${user.age}`;
}

console.log(describe({ name: "Ann", age: 30 })); // Ann, 30

Let's go through the example line by line:

  1. The parameter user has the type { name: string; age: number }: the object must have a property name holding a string and a property age holding a number.
  2. Inside the function TypeScript knows the shape of user, so to it user.name is a string and user.age is a number.
  3. The call passes an object that fits the form, and the program prints Ann, 30.

Writing an object type

An object type looks like an object, except that types stand to the right of the colons, not values. Let's take { name: string; age: number } apart:

  • the curly braces open and close the description of the shape;
  • name is the property's name;
  • the colon and string give the type of the value in that property;
  • a semicolon separates one property from the next; a comma works too, but types conventionally use semicolons.

Compare two pieces of code. { name: "Ann" } is an object with a value, and it exists while the program runs. { name: string } is a type, a description of a shape: only the compiler sees it, and it never reaches the JavaScript file.

For an object literal TypeScript infers the type itself. For example, after const user = { name: "Ann", age: 30 } the editor shows the type { name: string; age: number; } when you hover over user. You write the type by hand where there is nothing to infer it from, and most often that is a function parameter.

A missing property

The compiler checks the object against the whole form. If a required property is missing, it says which one:

TypeScript
const user: { name: string; age: number } = { name: "Ann" }; // ✗
TEXT
error TS2741: Property 'age' is missing in type '{ name: string; }' but required in type '{ name: string; age: number; }'.

The message reads like this: the type { name: string; } has no property age, while the type { name: string; age: number; } requires it. The first type is your literal as TypeScript saw it; the second is the form from the annotation.

If the property is there but its value has the wrong type, the error is a different one, TS2322. For example, age: "30" fails: the compiler says that a string cannot be assigned to the type number.

Here the form analogy stops working. A clerk also looks at the answers themselves, while TypeScript checks only types: it lets an age of -5 through, because that is a number.

A typo in a name

The form protects you when reading, too: a property the type does not list cannot be read.

TypeScript
const user: { name: string; age: number } = { name: "Ann", age: 30 };
console.log(user.nmae); // ✗
TEXT
error TS2339: Property 'nmae' does not exist on type '{ name: string; age: number; }'.

In JavaScript this line would print undefined, and you would have to hunt for the typo through odd output. TypeScript shows it at once, on the line where it was made.

Common mistake

A parameter got the type object to say "an object goes here":

TypeScript
function greet(user: object) {
    return `Hi, ${user.name}`; // ✗
}

console.log(greet({ name: "Ann" }));
TEXT
error TS2339: Property 'name' does not exist on type 'object'.

The type object means "some object" and says nothing about its properties. It is a form with no fields at all: you can read neither a name nor an age through it. List the properties the function needs: user: { name: string }.

Key points

  • An object type lists properties and their types: { name: string; age: number }.
  • TypeScript infers such a type for an object literal, while a function parameter gets it written by hand.
  • A missing required property is error TS2741; reading a property the type does not list is error TS2339.
  • The type object names no properties, so none can be read through it.