Summary

In this lesson, you learned that:

  • A function that should work with every type loses the type with any (bugs slip through) and with unknown (you must narrow after every call). One function per type repeats the same code. Generics solve this.
  • A generic function has a type parameter in angle brackets: function first<T>(items: T[]): T | undefined. T is a type that is filled in at each call: for first(names), T is string.
  • TypeScript infers the type arguments from the arguments. You can also write them, first<string>(names); that's needed when TypeScript would infer a type that's too narrow: fill<string | null>(null). A function can have several type parameters: pair<A, B>(first: A, second: B): [A, B].
  • string[] is short for Array<string>. With unions, Array<string | number> is often easier to read than (string | number)[]; string | number[] means something else. Record<K, V> is a generic type too.
  • Your own types can be generic: type Chest<T> = { location: string; loot: T };, interface Shelf<T> { items: T[] }. With a variable, you write the type argument: Chest<number>.
  • type Result<T> = { ok: true; value: T } | { ok: false; error: string }; describes the result of something that can fail; check if (result.ok) before you use result.value.
  • A constraint limits a type parameter: <T extends { power: number }>. Inside, thing.power is allowed, and the result keeps the caller's full type.
  • keyof Stats is the union of the keys of Stats. <K extends keyof Hero>(hero: Hero, key: K): Hero[K] reads a property by its key and returns its exact type.

In the next lesson, Classes, you'll create objects from templates: a class describes once what each hero or monster has and what it can do, and TypeScript checks all of it.

But first, put this lesson together. The shop sells potions and weapons, which are different types, but both have a price. In the editor, you'll find the Result type from this lesson and the shop's goods; the weapon shelf is empty today.

Instructions

Write a generic function cheapest<T extends { price: number }>(items: T[]): Result<T>. For an empty array, it fails with the error "nothing for sale". Otherwise, it succeeds, and its value is the item with the lowest price.

Find the cheapest potion with cheapest. If it succeeds, print the potion's name and how much it heals; if not, print the error:

Small Potion heals 5

Now do the same for the weapons: if cheapest succeeds, print the weapon's name and its damage, otherwise No weapon: and the error. The weapon shelf is empty, so the program prints:

Small Potion heals 5
No weapon: nothing for sale

Start programming for free

By signing up, you agree to the Terms of Service and Privacy Policy.

Or sign up with:

9/9