Just thought of another way to do it, without even using the tap operator.
const doTransfomration = data => data
.filter(x => x != null)
.map(x => x ** 2)
|> console.log(?) || ?
.filter(x => x > 100)
console.log(...) always returned undefined. So, console.log(...) || somethingElse will always cause the somethingElse to be evaluated and returned. This will effectivly cause the .filter() to be combined with the ?, which is exactly what we're wanting. |> console.log(?) || ?.filter(...)
This concept can also be used in a normal pipeline too:
const result = someData
|> parse(?)
|> filter(?)
|> console.log(?) || ?
|> format(?)
Not too shabby, eh?
This certainly satisfies my debugging needs - it's not difficult at all to put a ||? after the console.log, and it works in many scenarios.
Edit: I used || in these examples, because I often use || with console.log() when debugging expressions already. But, I guess a more general-purpose solution could be constructed by using the comma operator instead. This would allow us to have the tap operator, without extra syntax (though, I recognize that the comma operator isn't the most intuitive thing to use in production code).
const result = someData
|> parse(?)
|> filter(?)
|> doSomethingWithValue(?), ?
|> format(?)