Part 2: Higher-Order Functions and Composition - Building Pipelines

Introduction

I built a data processing service that transformed API responses through multiple steps: validate, filter, map, sort, paginate. My first version used nested loops and if statements - 200 lines of hard-to-follow code. Adding a new transformation step required understanding the entire flow.

I refactored using higher-order functions and composition. Each transformation became a small, focused function. Chained them together in a pipeline. The code shrunk to 50 lines. Adding new steps meant adding one function to the pipeline. That's when I understood the power of functional composition.

This article teaches you to use functions as first-class citizens, master map/filter/reduce, compose functions into pipelines, and build maintainable data transformations.

Functions as First-Class Citizens

In TypeScript, functions are values. You can:

  • Assign them to variables

  • Pass them as arguments

  • Return them from other functions

  • Store them in data structures

// Function as a value
const add = (a: number, b: number): number => a + b;
const multiply = (a: number, b: number): number => a * b;

// Store functions in an object
const operations = {
    add,
    multiply,
    subtract: (a: number, b: number): number => a - b
};

console.log(operations.add(5, 3));      // 8
console.log(operations.multiply(5, 3)); // 15

// Store functions in an array
const transforms: Array<(n: number) => number> = [
    n => n * 2,
    n => n + 10,
    n => n ** 2
];

// Apply all transforms
let value = 5;
for (const transform of transforms) {
    value = transform(value);
}
console.log(value);  // ((5 * 2) + 10) ** 2 = 400

Higher-Order Functions

A higher-order function either:

  1. Takes functions as arguments

  2. Returns a function

  3. Or both

Functions as Arguments

Functions as Return Values

Map, Filter, Reduce

The holy trinity of functional programming.

Map - Transform Each Element

Filter - Select Elements

Reduce - Aggregate to Single Value

Real Example: API Response Processing

I built a service that processes user data from an API:

Function Composition

Combine small functions into larger ones.

Manual Composition

Compose Utility

Pipe Utility

Real Example: Data Validation Pipeline

Real Example: Request/Response Pipeline

Point-Free Style

Functions without explicitly mentioned arguments.

Real Example: Data Processing Pipeline

Chaining Operations

Best Practices

1. Keep Functions Small and Focused

2. Use Descriptive Names

3. Prefer Declarative Over Imperative

What's Next

You now understand:

  • Functions as first-class citizens

  • Higher-order functions

  • Map, filter, reduce operations

  • Function composition and pipelines

  • Point-free style

  • Chaining operations

In Part 3: Closures and Currying, you'll learn to use closures for encapsulation, curry functions for flexibility, build function factories, and create reusable middleware patterns.


Based on building production TypeScript data processing pipelines, from API transformations to complex business logic.

Last updated