Quests

Now Kira's quest log. Every quest has a title, and it's open, done or failed. We've added Kira's quests under her in the data. Each status has its own data: only a done quest has a reward, and only a failed one has the reason why it failed. That's the shape from the lesson on modeling data, in which impossible combinations can't be written: a union with a tag, this time called status. For example, orders in a shop:

type Order =
    | { status: "waiting"; item: string }
    | { status: "sent"; item: string; days: number }
    | { status: "cancelled"; item: string; reason: string };

function describeOrder(order: Order): string {
    switch (order.status) {
        case "waiting":
            return `${order.item}: waiting`;
        case "sent":
            return `${order.item}: arrives in ${order.days} days`;
        case "cancelled":
            return `${order.item}: cancelled, ${order.reason}`;
    }
}

const orders: Order[] = [
    { status: "sent", item: "Rope", days: 2 },
    { status: "cancelled", item: "Lantern", reason: "out of stock" },
];
for (const order of orders) {
    console.log(describeOrder(order));
}

This prints:

Rope: arrives in 2 days
Lantern: cancelled, out of stock

This switch has no default with the never check, and it doesn't need one: the return type string does the job. If a status had no case, the function could end without returning anything, and TypeScript would report its first line: Function lacks ending return statement and return type does not include 'undefined'. Both ways are common: the exhaustiveness check also names the forgotten type, and the return type alone is shorter.

The quests in the data have no type yet, so TypeScript inferred one from the objects. Once you annotate the array with Quest[], TypeScript checks every quest against the union. A done quest without a reward, for example, would be reported:

main.ts(99,5): error TS2322: Type '{ status: "done"; title: string; }' is not assignable to type 'Quest'.
  Property 'reward' is missing in type '{ status: "done"; title: string; }' but required in type '{ status: "done"; title: string; reward: number; }'.

Instructions

Under Hero, write the type Quest: a union of three object types, each with a title (a text) and a status. An open quest has status: "open"; a done one status: "done" and a reward (a number); and a failed one status: "failed" and a reason (a text). Then annotate the array quests with Quest[].

Under findByName, write a function describeQuest(quest: Quest): string with a switch on quest.status. For an open quest, it returns [open] The Lost Crown, for a done one [done] Wolves in the Woods: +50 gold, and for a failed one [failed] Save the Miller: the mill burned down.

At the end of the main program, print Quests:, and then every quest in a for...of loop. The program ends like this:

Quests:
[done] Wolves in the Woods: +50 gold
[open] The Lost Crown
[failed] Save the Miller: the mill burned down
[done] The Goblin Bridge: +30 gold

Start programming for free

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

Or sign up with:

5/7