Everything you need to know about pipe and compose functions in JavaScript

Sumit Saha
4 min readMar 23, 2023

--

Pipe and Compose functions in JavaScript

Introduction

Functional programming is a programming paradigm that emphasizes writing code using functions as the primary building blocks. In functional programming, functions are treated as first-class citizens, which means they can be passed as arguments to other functions, returned from functions, and stored in variables.

In JavaScript, higher-order functions are functions that can accept other functions as arguments or return functions as their result. Two popular higher-order functions used in functional programming are the pipe and compose functions.

Pipe Function

The pipe function is a higher-order function that takes two or more functions as arguments and returns a new function. The returned function takes an input, applies each of the provided functions to it in order, passing the output of each function as the input to the next function. The final output is the result of the last function in the pipe.

Here’s an example of using the pipe function:

const pipe = (...fns) => (x) => fns.reduce((acc, f) => f(acc), x);

const addFive = (x) => x + 5;
const square = (x) => x * x;
const double = (x) => x * 2;

const result = pipe(addFive, square, double)(2); // Returns 98

console.log(result);

In this example, we define three functions: addFive, square, and double. We then use the pipe function to create a new function that applies each of these functions in order to the arguments (2). The result is the value 98.

Compose Function

The compose function is similar to the pipe function, but it applies the functions in the opposite order. The compose function takes two or more functions as arguments and returns a new function that applies each function in reverse order.

Here’s an example of using the compose function:

const compose = (...fns) => (x) => fns.reduceRight((acc, f) => f(acc), x);

const addFive = (x) => x+ 5;
const square = (x) => x * x;
const double = (x) => x * 2;

const result = compose(double, square, addFive)(2); // Returns 98

console.log(result);

In this example, we define three functions: addFive, square, and double. We then use the compose function to create a new function that applies each of these functions in reverse order to the arguments (2). The result is the value 98.

More Examples

There are many ways to use the pipe and compose functions in JavaScript. Here are some examples:

Example 1: Data Transformation

Suppose we have an array of user objects, and we want to sort the array by age, filter it to only include users with an age of 25, and then map the remaining users to their names. We can use the sort, filter, and map functions to accomplish this, but it can be hard to read and understand the code. Instead, we can use the pipe function to chain these functions together:

const users = [
{ name: 'Sumit', age: 38 },
{ name: 'Jasim', age: 30 },
{ name: 'Rahim', age: 20 },
];

const sortByAge = (a, b) => a.age - b.age;
const filterByAge = (age) => (user) => user.age === age;
const mapByName = (user) => user.name;

const result = pipe(
(users) => users.sort(sortByAge),
(users) => users.filter(filterByAge(38)),
(users) => users.map(mapByName)
)(users);

console.log(result); // Returns ['Sumit']

In this example, we define three functions: sortByAge, filterByAge, and mapByName. We then use the pipe function to chain these functions together to sort, filter, and map the users array. The final result is an array containing the names of users who are 38 years old.

Example 2: Function Composition

Suppose we have two functions, g and f, and we want to create a new function that applies g to the result of f. We can use the compose function to create this new function:

const g = (x) => x + 1;
const f = (x) => x * 2;

const h = compose(g, f);

console.log(h(3)); // Returns 7

In this example, we define two functions, g and f. We then use the compose function to create a new function h that applies g to the result of f. We can then call h with an argument of 3, which returns the value 7.

Example 3: Redux Middleware

In the Redux state management library, middleware is a function that intercepts actions dispatched to the store and can modify them, dispatch additional actions, or perform other side effects. Middleware functions are typically composed together using the compose function.

Here’s an example of using the compose function to create a Redux middleware:

const loggerMiddleware = (store) => (next) => (action) => {
console.log(`Action: ${action.type}, State: ${JSON.stringify(store.getState())}`);
return next(action);
};

const errorMiddleware = (store) => (next) => (action) => {
try {
return next(action);
} catch (error) {
console.error(`Error: ${error}`);
throw error;
}
};

const middleware = compose(loggerMiddleware, errorMiddleware);

// Usage in Redux store
const store = createStore(reducer, initialState, middleware);

In this example, we define two middleware functions, loggerMiddleware and errorMiddleware. We then use the compose function to create a new middleware function middleware that composes these two middleware functions together. We can then pass middleware to the createStore function when creating a Redux store to apply both middleware functions to actions dispatched to the store.

Conclusion

In conclusion, the pipe and compose functions are useful higher-order functions for functional programming in JavaScript. They allow you to chain together multiple functions to create a new function that applies all of the functions in a single operation. This can make your code more readable, concise, and composable.

--

--

Sumit Saha

A Full Stack Web Application Developer from Bangladesh 🇧🇩 & a Programming Content Creator. Spend most of time coding outstanding projects or creating contents