Why Generics

Some functions don't care what an array holds. A function that returns the first element works the same way for names, prices and heroes. In JavaScript, you would write it once:

function first(items) {
    return items[0];
}

In TypeScript, the parameter needs a type, otherwise you get Parameter 'items' implicitly has an 'any' type. (TS7006). But which type? The array can hold anything. Let's try the options you know.

Option 1: any. A parameter of type any[] accepts every array, and the function returns any:

type Hero = { name: string; health: number };

// Returns the first element of an array
function first(items: any[]): any {
    return items[0];
}

const heroes: Hero[] = [
    { name: "Kira", health: 50 },
    { name: "Bruno", health: 70 },
];
const potions: string[] = ["Healing Potion", "Mana Potion"];

const leader = first(heroes);
console.log(`Leader: ${leader.name}, health ${leader.helth}`);

const potion = first(potions);
console.log(potion.toUppercase());

This prints:

Leader: Kira, health undefined
TypeError: potion.toUppercase is not a function

TypeScript didn't report either typo. It doesn't know that leader is a hero and potion is a text: both are any, and with any, nothing is checked. The bugs of JavaScript are back: undefined instead of a number, and a crash while the program runs.

Option 2: unknown. In lesson 5, you met the safe version of any. With unknown, TypeScript doesn't let you use the result until you narrow it:

function first(items: unknown[]): unknown {
    return items[0];
}

const names = ["Kira", "Bruno", "Lena"];
const leader = first(names);
console.log(leader.toUpperCase());

TypeScript reports:

main.ts(7,13): error TS18046: 'leader' is of type 'unknown'.

That's safe, but not much use. You know that the first element of names is a text; TypeScript forgot it on the way through the function. You would have to check typeof leader === "string" after every call.

Option 3: a function for each type.

function firstName(names: string[]): string {
    return names[0];
}

function firstHero(heroes: Hero[]): Hero {
    return heroes[0];
}

Now TypeScript checks everything: firstHero(heroes).helth is an error. But both functions have the same body, and every new type needs another copy: firstPotion, firstQuest, firstMonster…

What we want is one function that says: “Whatever the type of the elements is, I return an element of that same type.” TypeScript has exactly this: generics, the topic of this lesson. You'll write your first generic function in the next exercise. First, try option 3 in the editor and see where it leads.

Instructions

Run the program: it prints health undefined and heals undefined, and TypeScript doesn't complain. Write a function firstHero(heroes: Hero[]): Hero with the same body as first, and use it for leader instead of first. TypeScript then finds the typo in the line with leader.helth. Fix it.

Do the same for potions: write firstPotion(potions: Potion[]): Potion, use it for potion, and fix the mistake TypeScript finds. The program then prints:

Leader: Kira, health 50
Potion: Healing Potion, heals 20

Now TypeScript checks both lines. But you have two functions with the same body, and the next type would need a third one. In the next exercise, a single function replaces them all.

Start programming for free

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

Or sign up with:

1/9