Итоги
В этом уроке вы узнали, что:
- Функция, которая должна работать с любым типом, теряет тип с
any(баги проскакивают) и сunknown(после каждого вызова приходится сужать тип). Отдельная функция для каждого типа повторяет один и тот же код. Эту задачу решают обобщения. - У обобщённой функции есть параметр типа в угловых скобках:
function first<T>(items: T[]): T | undefined.T— это тип, который подставляется при каждом вызове: дляfirst(names)T— этоstring. - TypeScript выводит аргументы типа из аргументов функции. Их можно и написать самому,
first<string>(names); это нужно, когда TypeScript вывел бы слишком узкий тип:fill<string | null>(null). У функции может быть несколько параметров типа:pair<A, B>(first: A, second: B): [A, B]. string[]— короткая записьArray<string>. С объединениямиArray<string | number>часто читается легче, чем(string | number)[]; аstring | number[]означает совсем другое.Record<K, V>— тоже обобщённый тип.- Свои типы тоже могут быть обобщёнными:
type Chest<T> = { location: string; loot: T };,interface Shelf<T> { items: T[] }. Для переменной аргумент типа нужно писать:Chest<number>. type Result<T> = { ok: true; value: T } | { ok: false; error: string };описывает результат того, что может не удаться; проверяйтеif (result.ok), прежде чем использоватьresult.value.- Ограничение сужает параметр типа:
<T extends { power: number }>. Внутри функцииthing.powerразрешён, а результат сохраняет полный тип, который был у вызывающего кода. keyof Stats— это объединение ключейStats. Запись<K extends keyof Hero>(hero: Hero, key: K): Hero[K]читает свойство по ключу и возвращает его точный тип.
В следующем уроке, «Классы», вы будете создавать объекты по шаблонам: класс один раз описывает, что есть у каждого героя или монстра и что он умеет, а TypeScript всё это проверяет.
Но сначала соберите этот урок воедино. В магазине продаются зелья и оружие — это разные типы, но у обоих есть price. В редакторе вы найдёте тип Result из этого урока и товары магазина; полка с оружием сегодня пуста.
Задание
- 1
Напишите обобщённую функцию
cheapest<T extends { price: number }>(items: T[]): Result<T>. Для пустого массива она возвращает неудачу с ошибкой"ничего нет в продаже". Иначе она возвращает успех, а значением будет предмет с самой низкой ценой. - 2
Найдите самое дешёвое зелье с помощью
cheapest. Если получился успех, выведите название зелья и сколько оно лечит; если нет — выведите ошибку:Малое зелье лечит 5 - 3
Теперь сделайте то же для оружия: если
cheapestвернула успех, выведите название оружия и егоdamage, иначе —Нет оружия:и ошибку. Полка с оружием пуста, поэтому программа выведет:Малое зелье лечит 5 Нет оружия: ничего нет в продаже