apple: { color: "red", mass: 100 },
grape: { color: "red", mass: 5 },
banana: { color: "yellow", mass: 183 },
lemon: { color: "yellow", mass: 80 },
pear: { color: "green", mass: 178 },
orange: { color: "orange", mass: 262 },
raspberry: { color: "red", mass: 4 },
cherry: { color: "red", mass: 5 },
interface Dict
{
[k: string]: T
// Array.prototype.map, but for Dict
function mapDict(input: Dict, transform: (item: T, key: string) => S): Dict {
const obj: Dict = {};
for (let x in input) {
obj[x] = transform(input[x], x);
return obj;
// Array.prototype.filter, but for Dict
function filterDict(input: Dict, predict: (item: T) => boolean): Dict {
const obj: Dict = {};
for (let x in input) {
if (predict(input[x])) {
obj[x] = input[x];
return obj;
// Array.prototype.reduce, but for Dict
function reduceDict(input: Dict, reducer: (acc: V, curr: T) => V, initialValue: V): V {
return Object.keys(input)
.reduce((acc, curr) => {
return reducer(acc, input[curr]);
}, initialValue)
Test:
// MAP
const fruitsWithKgMass = mapDict(fruits, (fruit, name) => ({
...fruit,
kg: 0.001 * fruit.mass,
name,
const lemonName: string = fruitsWithKgMass.lemon.name
// @ts-ignore-error
const failLemonName: number = fruitsWithKgMass.lemon.name
assertOk(
fruitsWithKgMass,
"[MAP] mapDict returns something truthy"
assertEquals(
fruitsWithKgMass.cherry.name,
"cherry",
'[MAP] .cherry has a "name" property with value "cherry"'
assertEquals(
fruitsWithKgMass.cherry.kg,
0.005,
'[MAP] .cherry has a "kg" property with value 0.005'
assertEquals(
fruitsWithKgMass.cherry.mass,
'[MAP] .cherry has a "mass" property with value 5'
assertEquals(
Object.keys(fruitsWithKgMass).length,
"[MAP] fruitsWithKgMass should have 8 keys"
// FILTER
// only red fruits
const redFruits = filterDict(
fruits,
(fruit) => fruit.color === "red"
assertOk(
redFruits,
"[FILTER] filterDict returns something truthy"
assertEquals(
Object.keys(redFruits).length,
"[FILTER] 4 fruits that satisfy the filter"
assertEquals(
Object.keys(redFruits).sort().join(", "),
"apple, cherry, grape, raspberry",
'[FILTER] Keys are "apple, cherry, grape, raspberry"'
// REDUCE
// If we had one of each fruit, how much would the total mass be?
const oneOfEachFruitMass = reduceDict(
fruits,
(currentMass, fruit) => currentMass + fruit.mass,
assertOk(
redFruits,
"[REDUCE] reduceDict returns something truthy"
assertEquals(
typeof oneOfEachFruitMass,
"number",
"[REDUCE] reduceDict returns a number"
assertEquals(
oneOfEachFruitMass,
"[REDUCE] 817g mass if we had one of each fruit"