How Pipeline Operator makes your code cleaner
Tags: javascript, babel, functional, ramda
Published: 2019-10-23 08:36:14


There's been talks of pipeline operator coming to ECMAScript for at least 2 years so this is no breaking news in any way :). There is a living proposal [here](https://github.com/tc39/proposal-pipeline-operator) with 2 possible variatons: F# and Smart pipelines. Both of them have their own **Babel plugins so you can try it anytime**.

And what's the **motivation** to use it? Without pipeline operator, you can either nest your function calls like this:

```js
// Using Ramda for the helper functions but lodash(/fp) would be quite similar
const { get, ... } = require('ramda');
const electronics = [{ title: ' iPhone ', type: 'phone' }];

const phones = trim(toUpper(prop('title', find(propEq('type', 'phone'), electronics)))); 
// => 'IPHONE'
```

and create unreadable mess or you can assign the function values to variables and end up with readable but verbose code.

**Pipeline operator to the rescue!** This recreates the above using the new syntax:

```js
const { get, ... } = require('ramda');
const electronics = [{ title: ' iPhone ', type: 'phone' }];

const phones = 
    electronics 
    |> find(propEq('type', 'phone')) 
    |> prop('title') 
    |> toUpper 
    |> trim
// => 'IPHONE'
```

**The code is terser and more readable as a single linear flow**.

---

*Side note: this is already achievable in a non-native fashion with e.g. RxJS or ramda/lodash's `pipe` (or `compose` for opposite order) as such:*

```js
const phones = pipe(
    find(propEq('type', 'phone')),
    prop('title'),
    toUpper,
    trim,
)(electronics)
```

## Topic reference 
This is probably the coolest thing about the proposal. Smart pipelines have something called topic reference, currently noted as `#` (in the end this could also be `?` or `%`) which represents the current value at the specific "step" inside of pipe.

What does this mean? Let's take a look at an example:

```js
Promise.resolve('post title ') 
    |> await # // Promise<resolved> => 'post title '
    |> typeof # === 'string' ? # : 'Untitled' // => 'post title '
    |> #.trim() // => 'post title'
    |> capitalize // => 'Post title'
    |> 'My Blog - ' + # // => 'My blog - Post title'
```

This is great because you can access the value directly without any need for curried functions. That means you can simply access value `#.length`,  call `#.trim()` or just use classic `lodash` functions like `endsWith(#, '...')`. Just **make sure you don't attempt to mutate  `#`** (e.g. `# = # * 5`) - it's unsupported and generally a bad practice.

## Real world use case
While this is all applicable very well in a lot of scenarios, one use case that I like the most is **validation**.

Imagine a function that validates email. With pipeline operator this would look like this:

```js
const gte = min => value => {
    if (value >= min) return value
    throw new Error('Value must be equal or greater than ' + min)
}
const lte = max => value => {
    if (value >= min) return value
    throw new Error('Value must be equal or smaller than ' + max)
}
const email = value => {
    if ("^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$".test(value)) return value
    throw new Error('Value is not an email')
}

const validateEmail = value => 
    value 
        |> gte(5)
        |> lte(10)
        |> email
```

While the `gte, lte, email` functions are still vanilla, the validateEmail readability is much higher!

---

This article just summaries thing I found interesting and it doesn't include everything. You might be able to use pipeline operator with prototypes, mixins, as an object decorator as mentioned [here](https://github.com/tc39/proposal-pipeline-operator).