Functions in map and filter
Arrays have methods that take a function as an argument. Two of them are used all the time, and they're new for you: map and filter. Both are plain JavaScript; TypeScript adds something useful to them.
map creates a new array. It calls your function for each element and puts what the function returns into the new array, in the same order:
const chests = [10, 25, 40];
const doubled = chests.map(gold => gold * 2);
console.log(doubled);
console.log(chests);This prints:
[20, 50, 80]
[10, 25, 40]map called gold => gold * 2 three times, with 10, 25 and 40, and collected the results. The original array chests didn't change. It does the same as this loop, just in one line:
const doubled: number[] = [];
for (const gold of chests) {
doubled.push(gold * 2);
}The function may return a value of another type. Then the new array has elements of that type:
const names = ["Kira", "Bruno", "Lena"];
console.log(names.map(name => name.toUpperCase()));
console.log(names.map(name => name.length));This prints:
["KIRA", "BRUNO", "LENA"]
[4, 5, 4]Notice that gold and name have no type, and TypeScript doesn't mind. That's the useful thing: TypeScript knows that chests is a number[], so the function given to map gets numbers, and gold is a number. The parameter gets its type from the place where the function is written (programmers call this contextual typing). TypeScript also knows what map returns: from gold * 2, an array of numbers, number[]. And because it knows that name is a string, it checks what you do with it:
const names = ["Kira", "Bruno", "Lena"];
const doubled = names.map(name => name * 2);main.ts(2,35): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.This only works when the function is written right where it's used, as an argument. An arrow function stored in a variable on its own still needs types, because TypeScript doesn't know where it will be used:
const double = gold => gold * 2;main.ts(1,16): error TS7006: Parameter 'gold' implicitly has an 'any' type.filter also creates a new array, but it keeps only some of the elements: those for which your function returns true:
const monsters = [
{ name: "goblin", power: 4 },
{ name: "troll", power: 15 },
{ name: "wolf", power: 8 },
{ name: "dragon", power: 40 },
];
const strong = monsters.filter(monster => monster.power > 10);
console.log(strong);
console.log(strong.map(monster => monster.name));This prints:
[{ name: "troll", power: 15 }, { name: "dragon", power: 40 }]
["troll", "dragon"]Here, monster gets the type of the array's elements, { name: string; power: number; }, so TypeScript catches a typo:
const monsters = [
{ name: "goblin", power: 4 },
{ name: "troll", power: 15 },
{ name: "wolf", power: 8 },
{ name: "dragon", power: 40 },
];
const strong = monsters.filter(monster => monster.pwer > 10);main.ts(7,51): error TS2551: Property 'pwer' does not exist on type '{ name: string; power: number; }'. Did you mean 'power'?The result of filter has the same type as the original array, so you can go on with it. The last line of the example calls map on the result to get just the names.
Typical mistakes:
- Curly braces without
return:chests.map(gold => { gold * 2 })gives[undefined, undefined, undefined]and the same mistake infiltergives[]. TypeScript doesn't report it here, so when you use curly braces, writereturn. - Expecting
maporfilterto change the array. They don't: they return a new array. Store it in a variable, or use it right away.
Instructions
Lucky day: the gold in every chest doubles. Call map on chests to create an array doubledGold with twice the gold of each chest.
Print doubledGold and then chests, to see that map didn't change the original array. The program prints:
[24, 60, 14, 90]
[12, 30, 7, 45]Kira only fights the strong monsters, those with a power greater than 10. Call filter on monsters to create an array strongMonsters with them.
Print strongMonsters, and then just the names of the strong monsters: call map on strongMonsters. At the end, the program prints:
[{ name: "troll", power: 25 }, { name: "skeleton", power: 12 }]
["troll", "skeleton"]Start programming for free
9/10