Инвентарь
Теперь рюкзак Киры. В нём три вида предметов: зелья, которые лечат, оружие, которое наносит урон, и ключи, которые что-то открывают. У каждого вида свои данные, поэтому для инвентаря подходит размеченное объединение (discriminated union) из урока «Моделирование данных». Каждый вид — отдельный объектный тип с тегом kind, а Item — объединение этих типов. Дайте каждому виду своё имя: Potion, Weapon и Key. На следующем шаге тип Weapon понадобится отдельно.
Чтобы описать предмет, используйте switch по тегу. В каждом case TypeScript знает, какой это вид предмета, поэтому в case "potion" можно использовать item.heal. А в default идёт проверка полноты с never из урока «Моделирование данных»: если когда-нибудь добавят новый вид, а его case забудут, TypeScript сообщит об этом прямо здесь. Например, заклинания:
type FireSpell = { kind: "fire"; name: string; damage: number };
type IceSpell = { kind: "ice"; name: string; turns: number };
type Spell = FireSpell | IceSpell;
function describeSpell(spell: Spell): string {
switch (spell.kind) {
case "fire":
return `${spell.name}: урон ${spell.damage}`;
case "ice":
return `${spell.name}: заморозка, ходов: ${spell.turns}`;
default:
const unhandled: never = spell;
return unhandled;
}
}
const spells: Spell[] = [
{ kind: "fire", name: "Огненный шар", damage: 30 },
{ kind: "ice", name: "Ледяная вспышка", turns: 2 },
];
for (const spell of spells) {
console.log(`- ${describeSpell(spell)}`);
}Это выведет:
- Огненный шар: урон 30
- Ледяная вспышка: заморозка, ходов: 2Предметы Киры попадают в новое свойство Hero — inventory: Item[]. В kira это массив объектов, и TypeScript проверяет каждый по его виду: зелье со свойством damage вместо heal было бы ошибкой. Затем основная программа выводит заголовок Инвентарь: и проходит по предметам циклом for...of.
Типичные ошибки:
- Заглавная буква в
case,case "Potion":. Тег — это в точности текст"potion", поэтому TypeScript сообщаетType '"Potion"' is not comparable to type '"key" | "potion" | "weapon"'., а из-за неё появится ещё несколько ошибок ниже. - Забытый case. Без
case "key"ключ попадает вdefault, и проверка сneverназывает его:main.ts(36,19): error TS2322: Type 'Key' is not assignable to type 'never'.
Задание
- 1
Под
HeroClassнапишите типыPotion(kind: "potion",nameи числоheal),Weapon(kind: "weapon",nameи числоdamage) иKey(kind: "key",nameи строкаopens), а такжеtype Item = Potion | Weapon | Key;. Добавьте вHeroсвойствоinventory: Item[]и дайте Кире три предмета:{ kind: "potion", name: "Целебное зелье", heal: 20 },{ kind: "weapon", name: "Серебряный меч", damage: 12 }и{ kind: "key", name: "Старый ключ", opens: "склеп" }. - 2
Под
describeHeroнапишите функциюdescribeItem(item: Item): stringсswitchпоitem.kindи проверкой сneverвdefault. Для зелья она возвращаетЦелебное зелье (лечит на 20), для оружия —Серебряный меч (урон 12), а для ключа —Старый ключ (открывает склеп). - 3
В основной программе под строкой о Кире выведите
Инвентарь:, а затем каждый предмет с-перед ним, в циклеfor...of:Кира, следопыт, уровень 3, здоровье 34/50, золото 120 Инвентарь: - Целебное зелье (лечит на 20) - Серебряный меч (урон 12) - Старый ключ (открывает склеп)