skies.dev

Introducing JavaScript's Pipe Operator

3 min read

In this article, I’m going to show you how to use JavaScript’s pipeline operator |> with Babel.

The pipeline operator is still experimental, so you should think of this as syntax that Babel can transform for you rather than something you can rely on in every JavaScript runtime today.

Set Up Babel

Start with a new project.

mkdir pipeline-operator-demo
cd pipeline-operator-demo
npm init -y

Then install Babel and the pipeline operator plugin.

npm install --save-dev @babel/core @babel/node @babel/preset-env @babel/plugin-proposal-pipeline-operator

Create a .babelrc file and tell Babel which pipeline proposal syntax to use.

.babelrc
{
  "presets": ["@babel/preset-env"],
  "plugins": [
    ["@babel/plugin-proposal-pipeline-operator", {"topicToken": "#", "proposal": "hack"}]
  ]
}

The important part here is the topicToken. In this setup, # represents the value flowing from one stage of the pipeline into the next.

Create an index.js file with a few small helper functions.

index.js
function add(x, y) {
  return x + y;
}

function square(x) {
  return x * x;
}

function double(x) {
  return x * 2;
}

Compare the Nested Version

Without the pipeline operator, the functions need to be nested manually.

index.js
function add(x, y) {
  return x + y;
}

function square(x) {
  return x * x;
}

function double(x) {
  return x * 2;
}

const result = double(square(add(1, 2)));

console.log(result);

Run it with babel-node index.js, and the result is 18.

The code works, but the data flow is buried inside the nested calls. You have to read from the inside out to understand what happens first.

Use the Pipeline Operator

Now rewrite the same logic with |>.

index.js
function add(x, y) {
  return x + y;
}

function square(x) {
  return x * x;
}

function double(x) {
  return x * 2;
}

const result = add(1, 2) |> square(#) |> double(#);

console.log(result);

If Unix pipes move text from one command to the next, the pipeline operator moves a value from one function call to the next.

Here is what happens step by step:

  1. add(1, 2) runs first and returns 3.
  2. 3 is passed into square(#), where # stands for the previous result. That produces 9.
  3. 9 is then passed into double(#), which produces 18.

The end result is the same as the nested version, but the flow reads left to right.

Conclusion

The main advantage of the pipeline operator is readability. It makes multi-step transformations feel like a sequence instead of a stack of nested calls.

If you want to experiment with it, Babel is the easiest place to start because it lets you try the syntax without waiting for native runtime support.

If you want to see the idea in a short demo, check out this YouTube short.

What do you think of the pipeline operator? Is the left-to-right style easier to read than the nested form?

Hey, you! 🫵

Did you know I created a YouTube channel? I'll be putting out a lot of new content on web development and software engineering so make sure to subscribe.

(clap if you liked the article)

You might also like