A proof-of-concept TypeScript compiler with a pipeline operator.
npm install -D @pengeszikra/typescript@next
I’d like you to experience the same flow I discovered about five years ago, when I had the chance to use the pipeline operator in a React project.
Back then, I was really into functional programming, especially the idea of building more complex workflows from small functions. With the right Babel configuration, I could already use a version of the pipeline proposal in JavaScript, including JSX.
And I loved it.
The basic idea is simple: reverse the familiar function-call notation.
// Example code by OpenAI Codex.
transform(input);
input |> transform;
On its own, this might not seem like a major invention. But once you start connecting several functions, the difference becomes clear:
// Example code by OpenAI Codex.
f(g(h(j(input))));
input |> j |> h |> g |> f;
In the first version, we read the function names from the outside in, while the data is processed from the inside out. In the second, the code reads in the same direction as the process.
First, we have the data. Then, we describe what happens to it.
To me, that feels much more natural.
It looks a little like familiar JavaScript method chains, such as text.trim().toLowerCase(). With method chaining, however, each subsequent operation must be available as a method on the current value.
With a pipeline, the functions can remain independent. There is no need to attach them to the data, organize them into a shared class, or build a special chainable API. They can even come from entirely different modules.
The data’s type can also change along the way:
// Example code by OpenAI Codex.
const trim = (text: string): string => text.trim();
const count = (text: string): number => text.length;
const double = (value: number): number => value * 2;
const describe = (value: number): string => `Result: ${value}`;
const result = " pipe "
|> trim
|> count
|> double
|> describe;
// "Result: 8"
Each stage receives the previous stage’s return value as its single argument. TypeScript checks whether that value is compatible with the next function’s input type and infers the result type of the entire expression.
We can describe an easy-to-follow workflow using functions that are independently reusable and testable. And we avoid nesting parentheses along the way.
For me, that readability was particularly valuable in React. That is why supporting both .ts and .tsx files was an essential requirement for this implementation:
// Example code by OpenAI Codex.
// InputHandler is an ordinary data-processing function here.
<InteractiveElement>{input |> InputHandler}</InteractiveElement>
In an earlier article, I suggested that a TypeScript fork could be a good place to experiment with this. I started working on it back then, but never finished.
Now, years later, I’ve returned to it with AI assistance — GPT-6. This time, we started with the Go-based TypeScript compiler and built a working proof of concept.
Its purpose is simple: let developers explore this programming style in real TS and TSX code, with type checking.
To try it:
# Commands prepared by OpenAI Codex.
npm install -D @pengeszikra/typescript@next
npx tspipe --project tsconfig.json
This is an experimental compiler with its own tspipe command. Installing it does not automatically add pipeline support to your editor or bundler: you need to compile the new syntax to JavaScript using this compiler.
One clarification about “single-input” behavior: the pipeline always passes exactly one argument. The current POC uses TypeScript’s normal call checking, so it does not separately prohibit optional or rest parameters.
I’m curious how it feels to you. Which of your workflows would become easier to read as a pipeline? Where does it help, and where does it feel unnecessary?
If you’d like to experience the same flow I did, give this pipe a try.
Please try it — and, even better, try to break it.
My initial testing has been limited, and passing those tests does not mean we have covered every real-world use case. Put it into a small project, build some unusual function chains, try it in TSX, and see where the type checker or the generated JavaScript surprises you.
If you find a bug, please open an issue with a minimal example, what you expected, what actually happened, and your tspipe --version output. Feedback on the syntax and readability is just as welcome as compiler bug reports.
The more people explore it, the better we can understand what works, what needs fixing, and whether this could become a useful language feature. Your experiments can help turn a personal proof of concept into evidence that others can build on.
If the idea proves useful in practice, perhaps it could eventually contribute to pipeline support in TypeScript and JavaScript. A working fork does not guarantee adoption, but it gives us something concrete to try, discuss, and improve.
And one more thing: just because we increasingly write code with AI does not mean we should forget how to program — or stop wanting better programming languages. We still need to think about how code expresses our intentions, how easily we can understand it, and how our tools could serve us better.
AI helped me build this experiment. What makes it worth building is the human experience of programming with it.
Use this PIPE to feel the FLOW. - vibe archeologist
Top comments (0)