Understanding Higher-Order Functions in TypeScript: An Example with Circles
Introduction
Higher-order functions are a fundamental pillar of functional programming. These functions operate on other functions by accepting them as arguments or returning them as results. This concept can sometimes seem abstract, so in this blog post, we’ll explore higher-order functions in TypeScript through the concrete example of calculating various properties of circles.
What are Higher-Order Functions?
A higher-order function is one that does at least one of the following:
- Accepts one or more functions as arguments
- Returns a function as a result
In practice, higher-order functions provide a powerful way to create reusable and flexible code structures.
Circle Calculations Example
Let’s imagine that we have a set of circles, each defined by its radius. We want to calculate the diameter, circumference, and area of each circle. We can approach this problem by creating a higher-order function that accepts an array of radii as input and returns an object with functions for each calculation we want to perform.
Firstly, let’s define a type for functions that take a single number argument (the radius) and return a number:
type CircleCalculator = (radius: number) => number;
Now let’s dive into the higher-order function:
function circleCalculations(radii: number[]) {
const calculate = (fn: CircleCalculator) : number[] => radii.map(fn);
return {
calculateDiameters: () => calculate(radius => 2 * radius),
calculateCircumferences: () => calculate(radius => 2 * Math.PI * radius),
calculateAreas: () => calculate(radius => Math.PI * radius * radius),
};
}
In this function, calculate
is a helper higher-order function that takes a CircleCalculator
function as an argument and applies it to each radius in the input array. The circleCalculations
function then returns an object with three methods (calculateDiameters
, calculateCircumferences
, calculateAreas
), each of which uses calculate
to map over the radii and perform the respective calculation.
Using this setup, we can easily compute our circle properties:
let circles = circleCalculations([1, 2, 3, 4, 5]); // array of radii
console.log(circles.calculateDiameters()); // [2, 4, 6, 8, 10]
console.log(circles.calculateCircumferences()); // [6.28, 12.57, 18.85, 25.13, 31.42]
console.log(circles.calculateAreas()); // [3.14, 12.57, 28.27, 50.27, 78.54]
Conclusion
This example showcases the power and flexibility of higher-order functions. By allowing us to define a generic calculation operation and then apply it in different ways, we can create highly reusable and readable code structures. In TypeScript, this concept is further enhanced with static types, allowing us to ensure that our functions are used correctly. As you continue to explore TypeScript and functional programming, remember the power of higher-order functions and leverage them in your code.