Объединения типов
Не у каждого значения только один тип. Когда Кира выполняет квест, её награда бывает то золотом — числом вроде 50, то предметом — строкой вроде "Серебряный меч". С известными вам типами одна переменная не может хранить и то, и другое:
let reward = 50;
reward = "Серебряный меч";main.ts(2,1): error TS2322: Type 'string' is not assignable to type 'number'.Для таких значений в TypeScript есть объединения типов (union types). Вы пишете несколько типов через вертикальную черту | и читаете её как «или»: number | string — это «число или строка».
let reward: number | string = 50;
console.log(reward);
reward = "Серебряный меч";
console.log(reward);Программа выведет:
50
Серебряный мечТеперь в reward может лежать число или строка, но больше ничего. Если дописать в конец строку reward = true;, TypeScript сообщит:
main.ts(5,1): error TS2322: Type 'boolean' is not assignable to type 'string | number'.В сообщении объединение записано как string | number, хотя в коде стоит number | string. Порядок не важен: оба варианта означают один и тот же тип. В объединении может быть и больше типов, например string | number | boolean. А с объединением вы уже встречались: необязательный параметр title?: string имеет тип string | undefined.
Чаще всего объединения нужны для параметров. Эта функция принимает награды обоих видов:
function showReward(reward: string | number): void {
console.log(`Ваша награда: ${reward}`);
}
showReward(50);
showReward("Серебряный меч");Программа выведет:
Ваша награда: 50
Ваша награда: Серебряный мечНо что функция может делать с reward? Только то, что работает для каждого типа из объединения. Вывод работает и для чисел, и для строк, шаблонная строка тоже. А метод строки — нет:
function shoutReward(reward: string | number): string {
return reward.toUpperCase();
}main.ts(2,19): error TS2339: Property 'toUpperCase' does not exist on type 'string | number'.
Property 'toUpperCase' does not exist on type 'number'.В этом сообщении две строки. Первая говорит, что у объединения string | number нет toUpperCase, а вторая, с отступом, объясняет почему: у number его нет. TypeScript не может знать, какой тип получит функция, когда программа запустится. Если ей достанется 50, JavaScript завершится с ошибкой TypeError: reward.toUpperCase is not a function. Поэтому TypeScript разрешает только то, что безопасно для обоих типов. С арифметикой так же: reward * 2 тоже ошибка, ведь наградой может оказаться строка.
В следующем упражнении вы узнаете, как выяснить, какой тип у значения, чтобы вызывать методы строк у строк и считать с числами.
Типичная ошибка: две черты вместо одной. В типах черта одна; let reward: number || string = 50; — это недопустимый TypeScript, и компилятор теряется:
main.ts(1,20): error TS1005: ',' expected.
main.ts(1,30): error TS1005: ';' expected.Задание
- 1
Запустите программу: TypeScript не позволяет положить строку в
reward. Измените типrewardна объединениеnumberиstring, чтобы программа вывела:Награда: 50 Награда: Серебряный меч - 2
Ниже напишите функцию
announceс одним параметромrewardтипаstring | number. Функция выводитКвест выполнен! Награда:и саму награду. - 3
Вызовите
announceдважды: со значением120и со значением"Старый ключ". Тогда программа выведет:Награда: 50 Награда: Серебряный меч Квест выполнен! Награда: 120 Квест выполнен! Награда: Старый ключ