When find() Finds Nothing

To look for one thing in an array, JavaScript has the method find(). It works like filter() from the Functions lesson: you give it a function, and it calls that function for the elements one by one. But it doesn't return an array of all the matches. It returns the first element for which the function returns true, and stops looking:

type Monster = { name: string; strength: number };

const monsters: Monster[] = [
    { name: "goblin", strength: 4 },
    { name: "wolf", strength: 7 },
    { name: "troll", strength: 15 },
    { name: "dragon", strength: 40 },
];

const strong = monsters.find(monster => monster.strength > 10);
console.log(strong);
const giant = monsters.find(monster => monster.strength > 100);
console.log(giant);

This prints:

{ name: "troll", strength: 15 }
undefined

The troll is the first monster stronger than 10. No monster is stronger than 100, so the second search found nothing, and find() returned undefined.

That's why the type of the result isn't Monster, but Monster | undefined. And TypeScript won't let you use it as a monster until you check it. With the same array:

const strong = monsters.find(monster => monster.strength > 10);
console.log(`The first strong monster is the ${strong.name}`);
main.ts(11,48): error TS18048: 'strong' is possibly 'undefined'.

You can see a troll in the array, but TypeScript doesn't look at the data: the array could change, and so could the condition. In JavaScript, a search that found nothing would crash the program later, with TypeError: Cannot read properties of undefined (reading 'name'), often far from the search itself. TypeScript makes you think about “nothing found” right where it can happen:

const strong = monsters.find(monster => monster.strength > 10);
if (strong === undefined) {
    console.log("No strong monster here");
} else {
    console.log(`The first strong monster is the ${strong.name}`);
}

This prints:

The first strong monster is the troll

A function that searches has to say it in its return type too. If it promises a Monster, TypeScript reports its return (again below the same array):

function findMonster(name: string): Monster {
    return monsters.find(monster => monster.name === name);
}
main.ts(11,5): error TS2322: Type 'Monster | undefined' is not assignable to type 'Monster'.
  Type 'undefined' is not assignable to type 'Monster'.

The fix is the honest return type, Monster | undefined. Whoever calls the function then checks the result.

Typical mistake: = instead of === in the function. monsters.find(monster => monster.name = "wolf") doesn't compare: it renames the first monster to "wolf" and returns it, so you get { name: "wolf", strength: 4 }, the renamed goblin. TypeScript doesn't report this, because find() accepts any value as the function's answer.

Instructions

Run the program and fix the errors: when key is undefined, print No Old Key in the inventory; otherwise, print its name and price as before. The program then prints:

Old Key: 5 gold

Below, write a function findItem with a parameter name (a text), which returns the item from inventory that has this name. Use find(), and give the function the right return type.

Use findItem for the names "Silver Sword" and "Dragon Egg". For an item that exists, print its name and price as above; for one that doesn't, print No Dragon Egg in the inventory (with the name you looked for). The program then prints:

Old Key: 5 gold
Silver Sword: 80 gold
No Dragon Egg in the inventory

Start programming for free

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

Or sign up with:

5/10