Один или много: Array.isArray
Некоторым функциям удобнее принимать одно значение или несколько. В сундуке может лежать один предмет или список предметов, и хочется вызывать одну и ту же функцию в обоих случаях: openChest("Серебряный меч") и openChest(["Лечебное зелье", "Верёвка"]). Тип такого параметра — string | string[]: строка или массив строк.
Сравните его с типом массива из упражнения про typeof: string | string[] — это «одна строка или массив строк», а (string | number)[] — «массив, элементы которого — строки или числа». Скобки определяют, к чему относится [].
Как выяснить, что вам пришло? typeof не умеет узнавать массив: для массива он выдаёт "object", как и для любого объекта. (Здесь сработало бы и typeof loot === "string", ведь другой вариант — только массив.) В JavaScript есть функция, созданная для массивов: Array.isArray(value) возвращает true, если значение — массив, и false в остальных случаях. TypeScript её понимает и сужает тип:
function openChest(loot: string | string[]): void {
if (Array.isArray(loot)) {
for (const item of loot) {
console.log(`Вы находите: ${item}`);
}
} else {
console.log(`Вы находите: ${loot}`);
}
}
openChest(["Лечебное зелье", "Верёвка"]);
openChest("Серебряный меч");Программа выведет:
Вы находите: Лечебное зелье
Вы находите: Верёвка
Вы находите: Серебряный мечВнутри if loot — это string[], в ветке else — string. Без проверки TypeScript разрешает только то, что работает для обоих типов, а методы массива к этому не относятся:
function openChest(loot: string | string[]): void {
loot.push("Верёвка");
}main.ts(2,10): error TS2339: Property 'push' does not exist on type 'string | string[]'.
Property 'push' does not exist on type 'string'.Но будьте осторожны: кое-что работает для обоих типов, и тогда TypeScript не возражает, даже если результат получается не тот, что вы хотели. И у строк, и у массивов есть length, и перебирать можно и то и другое через for...of. Без проверки openChest("Верёвка") перебрал бы буквы строки:
function openChest(loot: string | string[]): void {
for (const item of loot) {
console.log(`Вы находите: ${item}`);
}
}
openChest("Верёвка");Программа выведет:
Вы находите: В
Вы находите: е
Вы находите: р
Вы находите: ё
Вы находите: в
Вы находите: к
Вы находите: аTypeScript проверяет, что ваши действия допустимы для этих типов. Проверить, то ли это, что вы хотели, он не может.
Задание
- 1
Программа выводит
3и14. TypeScript разрешаетloot.length, потому что у строк тоже естьlength, но для"Серебряный меч"это количество символов. ИсправьтеcountItemsс помощьюArray.isArray, чтобы один предмет считался за 1. Тогда программа выведет:3 1 - 2
Ниже напишите функцию
showLootс параметромlootтипаstring | string[]. Она выводит каждый предмет на отдельной строке, а перед ним —-. - 3
Вызовите
showLootдля тех же двух сундуков. Тогда программа выведет:3 1 - Лечебное зелье - Старый ключ - Верёвка - Серебряный меч