Optional Properties

Not every hero has a nickname. For a property that may be missing, put a question mark after its name, just as with optional parameters:

type Hero = { name: string; level: number; nickname?: string };

const kira: Hero = { name: "Kira", level: 3, nickname: "Swift Arrow" };
const bruno: Hero = { name: "Bruno", level: 2 };

console.log(bruno);
console.log(bruno.nickname);

This prints:

{ name: "Bruno", level: 2 }
undefined

An optional property may be left out of the object, and TypeScript doesn't report it as missing. Reading it gives its value, or undefined when it isn't there, just as in JavaScript. So the type of bruno.nickname is string | undefined, and before you use it as a string, TypeScript wants a check:

type Hero = { name: string; level: number; nickname?: string };

const kira: Hero = { name: "Kira", level: 3, nickname: "Swift Arrow" };
console.log(kira.nickname.toUpperCase());
main.ts(4,13): error TS18048: 'kira.nickname' is possibly 'undefined'.

Kira does have a nickname, and TypeScript still reports it. It doesn't look at the value, but at the type: kira is a Hero, and a hero's nickname may be missing. Check it the same way as an optional parameter:

type Hero = { name: string; level: number; nickname?: string };

function heroTitle(hero: Hero): string {
    if (hero.nickname === undefined) {
        return hero.name;
    }
    return `${hero.name} "${hero.nickname.toUpperCase()}"`;
}

console.log(heroTitle({ name: "Kira", level: 3, nickname: "Swift Arrow" }));
console.log(heroTitle({ name: "Bruno", level: 2 }));

This prints:

Kira "SWIFT ARROW"
Bruno

You may also set an optional property later: bruno.nickname = "the Bear"; is fine, because the type says that a hero may have a nickname. A property that isn't in the type can't be added, as you know.

When should a property be optional? When it's normal for it to be missing: a nickname, a weakness, a weapon the hero doesn't have yet. When every object must have the property, keep it required. Then TypeScript checks that you haven't forgotten it.

Typical mistakes:

  • Using the property without a check: 'kira.nickname' is possibly 'undefined'.
  • Putting it into a template literal without a check. TypeScript doesn't stop you there: ${bruno.nickname} becomes the text undefined.

Instructions

Not every monster has a weakness, but the skeleton has one, and TypeScript reports it. Add an optional property weakness of type string to Monster. The program prints:

wolf (30 health)
skeleton (25 health)

Change describe: when the monster has a weakness, the function adds it to the text in capital letters. The program then prints:

wolf (30 health)
skeleton (25 health), weak against LIGHT

Create a dragon of type Monster, with 300 health and the weakness "ice", and print describe(dragon). At the end, the program prints:

dragon (300 health), weak against ICE

Start programming for free

By signing up, you agree to the Terms of Service and Privacy Policy.

Or sign up with:

4/10