Introducing JavaScript's Pipe Operator
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.
{
"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.
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.
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 |>.
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:
add(1, 2)runs first and returns3.3is passed intosquare(#), where#stands for the previous result. That produces9.9is then passed intodouble(#), which produces18.
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?