Когда find() ничего не находит
Чтобы найти в массиве один элемент, в JavaScript есть метод find(). Он работает как filter() из урока «Функции»: вы передаёте ему функцию, и он вызывает её для элементов по очереди. Но возвращает он не массив всех совпадений, а первый элемент, для которого функция вернула true, и на этом останавливается:
type Monster = { name: string; strength: number };
const monsters: Monster[] = [
{ name: "гоблин", strength: 4 },
{ name: "волк", strength: 7 },
{ name: "тролль", strength: 15 },
{ name: "дракон", strength: 40 },
];
const strong = monsters.find(monster => monster.strength > 10);
console.log(strong);
const giant = monsters.find(monster => monster.strength > 100);
console.log(giant);Программа выведет:
{ name: "тролль", strength: 15 }
undefinedТролль — первый монстр сильнее 10. Монстра сильнее 100 нет, поэтому второй поиск ничего не нашёл, и find() вернул undefined.
Поэтому тип результата — не Monster, а Monster | undefined. И TypeScript не позволит использовать его как монстра, пока вы его не проверите. С тем же массивом:
const strong = monsters.find(monster => monster.strength > 10);
console.log(`Первый сильный монстр: ${strong.name}`);main.ts(11,39): error TS18048: 'strong' is possibly 'undefined'.В массиве виден тролль, но TypeScript не смотрит на данные: массив может измениться, как и условие. В JavaScript поиск, который ничего не нашёл, позже привёл бы к сбою программы с TypeError: Cannot read properties of undefined (reading 'name') — часто далеко от самого поиска. TypeScript заставляет подумать о «ничего не найдено» именно там, где это может случиться:
const strong = monsters.find(monster => monster.strength > 10);
if (strong === undefined) {
console.log("Сильных монстров здесь нет");
} else {
console.log(`Первый сильный монстр: ${strong.name}`);
}Программа выведет:
Первый сильный монстр: тролльФункция, которая ищет, тоже должна сказать об этом в типе возвращаемого значения. Если она обещает Monster, TypeScript сообщит об ошибке в её return (снова под тем же массивом):
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'.Исправление — честный тип возвращаемого значения, Monster | undefined. Тот, кто вызывает функцию, затем проверяет результат.
Типичная ошибка: = вместо === в функции. monsters.find(monster => monster.name = "волк") ничего не сравнивает: она переименовывает первого монстра в "волк" и возвращает его, так что вы получите { name: "волк", strength: 4 } — переименованного гоблина. TypeScript этого не замечает, потому что find() принимает в качестве ответа функции любое значение.
Задание
- 1
Запустите программу и исправьте ошибки: если
keyравенundefined, выведитеВ инвентаре нет: Старый ключ; иначе выведите название и цену, как раньше. Тогда программа выведет:Старый ключ, цена: 5 - 2
Ниже напишите функцию
findItemс параметромname(строка), которая возвращает предмет изinventoryс таким названием. Используйтеfind()и задайте функции правильный тип возвращаемого значения. - 3
Примените
findItemк названиям"Серебряный меч"и"Драконье яйцо". Для существующего предмета выведите его название и цену, как выше; для несуществующего выведитеВ инвентаре нет: Драконье яйцо(с тем названием, которое вы искали). Тогда программа выведет:Старый ключ, цена: 5 Серебряный меч, цена: 80 В инвентаре нет: Драконье яйцо