Back to Blog
Advanced2026-04-05

The Pipeline Operator: Cleaner Function Composition in JavaScript

Learn the TC39 pipeline operator proposal and how it transforms nested function calls into readable left-to-right chains.

The Problem: Nested Function Calls

Functional programming in JavaScript often leads to deeply nested, hard-to-read code. When you compose multiple transformations, you read them inside-out:

``javascript // Reading order: exclaim → capitalize → trim → greet // But written as: greet(trim(capitalize(exclaim(name)))) const result = greet(trim(capitalize(exclaim(name))));

// Or with intermediate variables (verbose): const step1 = exclaim(name); const step2 = capitalize(step1); const step3 = trim(step2); const result = greet(step3); `

Both approaches are suboptimal. The pipeline operator fixes this by letting you write transformations in natural reading order.

The Hack-Style Pipeline Operator

The TC39 proposal uses the "hack-style" pipeline where \%\ (or another token) represents the value being piped:

`javascript // Clean, left-to-right reading order const result = name |> exclaim(%) |> capitalize(%) |> trim(%) |> greet(%);

// Real-world example: data transformation const processedUsers = rawData |> JSON.parse(%) |> %.users |> %.filter(u => u.active) |> %.map(u => ({ ...u, name: u.name.trim() })) |> %.sort((a, b) => a.name.localeCompare(b.name)); `

Practical Data Processing

`javascript // Without pipeline — hard to follow const report = formatReport( aggregate( normalize( filterOutliers( parseCSV(rawInput), { threshold: 2 } ) ) ), { format: 'markdown' } );

// With pipeline — reads like a recipe const report = rawInput |> parseCSV(%) |> filterOutliers(%, { threshold: 2 }) |> normalize(%) |> aggregate(%) |> formatReport(%, { format: 'markdown' }); `

Combining with Async/Await

The pipeline operator works seamlessly with async functions:

`javascript const userData = userId |> await fetchUser(%) |> %.profile |> enrichWithAnalytics(%) |> await saveToCache(%); `

Simulating Pipelines Today

While we wait for the proposal to ship, you can simulate pipelines:

`javascript // Helper function function pipe(value, ...fns) { return fns.reduce((acc, fn) => fn(acc), value); }

const result = pipe( name, exclaim, capitalize, trim, greet );

// Or with Array.prototype method chaining pattern const result = [name] .map(exclaim) .map(capitalize) .map(trim) .map(greet)[0]; ``

The pipeline operator is one of the most anticipated JavaScript proposals. It makes functional composition readable and eliminates the need for deeply nested function calls or unnecessary intermediate variables. Keep an eye on its progress through TC39.