JavaScript is mostly about functions. We can: 1) assign them to variables, 2) use as arguments to other functions, 3) return a function from a function.
Higher order function is a function that applies to point 2 or 3. In this post, I’d like to show how I implemented my own versions of some built-in language higher order functions using TypeScript. I did not cover Array.prototype.reduce in this post. Hopefully, I will implement this soon.
Interface
First, I create an interface to set a structure for my methods implementation. Notice that I use typescript generics here. An array can consist of items of different types and generics are a good solution for such situations. Thanks to it we make this implementation more reusable. We won’t lose the information about the passed array type also.
interface Array<T> {
myForeach(cb: (element: T, index: number, arr: T[]) => void): undefined;
myFilter(cb: (element: T, index: number, arr: T[]) => boolean): T[];
myMap(cb: (element: T, index: number, arr: T[]) => T): T[];
}
ForEach
Let’s start with Array.prototype.forEach. This method executes a callback once for each element in the provided array. Here’s my version of it. Notice that returned value is undefined since this method does not return an array, like the other higher order functions we know from JavaScript.
Array.prototype.myForeach = function<Each>(callback: (element: Each, index: number, arr: Each[]) => void): undefined {
for (let i = 0; i < this.length; i++) {
callback(this[i], i, this);
}
return undefined
}
Map
Here we need to set the type for the returned (ChangedMapElem) array, not only the passed one.
Array.prototype.myMap = function<MapElem, ChangedMapElem>(callback: (element: MapElem, index: number, arr: MapElem[]) => ChangedMapElem): ChangedMapElem[] {
let mapped = [];
for (let i = 0; i < this.length; i++) {
mapped.push(callback(this[i], i, this))
}
return mapped;
}
Filter
Array.prototype.myFilter = function<FilterElem>(callback: (element: FilterElem, index: number, arr: FilterElem[]) => boolean): FilterElem[] {
let filtered = [];
for (let i = 0; i < this.length; i++) {
if (callback(this[i], i, this)) filtered.push(this[i]);
}
return filtered;
}
That’s it. I made it just for practice, to solidify my JavaScript/TypeScript skills. I don’t encourage you to use your own implementations of methods that are already built into the language. These are well optimized and opinionated so let’s stick to language base principles and tools.