Model or dataset
marpple/FxTS avatar
marpple/FxTS

FxTS treats a pipeline as something you can stop halfway through

A functional programming library for TypeScript/JavaScript

1,168 stars86 forksTypeScriptApache-2.0

At a glance

What is it?
FxTS is a TypeScript functional programming library built on the standard iteration protocols, so the same pipe and map work over arrays, over async iterables from an LLM stream or a paginated API, and over promises. The version 2.0 release dropped the older API and the comparison table against lodash and native iterator helpers is unusually blunt.
Who is it for?
Adopt FxTS if your TypeScript code is full of promise chains and sequential awaits that could be concurrent, since the library's `concurrent` combinator and its async iterable pipelines address exactly that. Do not adopt it in a codebase that only maps over arrays, because plain native code does that better, and note the table in the project documentation says as much.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 57 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

One pipeline over three kinds of source

The architectural decision is that everything is built on the standard iteration protocols, and the README is specific about what follows from that. Because FxTS speaks the iteration protocol, the same functions work over arrays, over async iterables and over promises, and the documentation calls out the three sources that matter in practice: LLM SDK streams, Node.js streams and paginated APIs are pipelines out of the box. That is a real difference in ergonomics. A pipeline written once can consume a page-by-page API on one end and an in-memory array on the other without being rewritten, because the lazy evaluation happens over an iterator rather than over a concrete collection. The package is published as `@fxts/core` and the documented install is a single npm command.

Lazy evaluation is the default, not an opt-in mode

The library provides lazy evaluation for memory-efficient data processing with functions like `pipe`, `map`, `filter` and `take`. The word lazy here carries the usual meaning, that nothing is computed until it is pulled, but the practical consequence in a pipeline with `take` is early termination: the upstream work stops once you have enough elements. The comparison table lists early termination across async work as a capability of FxTS that lodash does not have and that native iterator helpers only offer in the synchronous case. That is the feature that decides whether you need the library, because a `take` after an async `map` in a hand-rolled promise chain usually means you have already done all the work.

pipe is curried, data-last, and unwraps promises

The composition function is `pipe`, and the table gives it two properties that matter. It is curried and data-last, so you write the transformations in the order you read them and the data goes in last, which is the opposite of the method chaining style. And it infers `Awaited` values, so a pipe whose steps return promises has a type that reflects the resolved value rather than a nested promise type. The usage example shows both styles, since the library also offers `fx` for method chaining:

ts
import { each, filter, fx, map, pipe, range, take } from "@fxts/core";

pipe(
  range(10),
  map((a) => a + 10),
  filter((a) => a % 2 === 0),
  take(2),
  each((a) => console.log(a)),
);

// chaining
fx(range(10))
  .map((a) => a + 10)
  .filter((a) => a % 2 === 0)
  .take(2)
  .each((a) => console.log(a));

The two forms are equivalent, and having both means the library fits either the codebase's existing habit or the reviewer who prefers the other.

concurrent is the part that changes runtime behaviour

The concurrency example is the clearest argument for the library, because it shows a wall clock difference rather than a style preference. A helper fetches a page from an API, and a pipeline turns the list into async work with `toAsync`, maps it through the fetch and the text and the split, flattens it, and then applies `concurrent`:

ts
import { concurrent, countBy, flat, fx, map, pipe, toAsync } from "@fxts/core";

const countWords = async (concurrency: number) =>
  pipe(
    ["html", "css", "javascript", "typescript"],
    toAsync,
    map(fetchWiki),
    map((res) => res.text()),
    map((words) => words.split(" ")),
    flat,
    concurrent(concurrency),
    countBy((word) => word),
  );

The documentation annotates the results as four seconds for the unbounded call and two seconds for the concurrency of two, and the difference is exactly the point: the pipeline expresses the shape and the concurrency limit is a parameter rather than a rewrite. The table also lists concurrency control with backpressure through `concurrentPool`, which neither lodash nor the native iterator helpers offer, and the project ships a migration guide for people coming from `p-limit` and `p-map`.

The comparison table is an argument, not a summary

The table that motivates the project compares FxTS, lodash and the native Array plus Iterator Helpers, across eight capabilities. FxTS is marked as having lazy evaluation, async iterable pipelines, concurrency control with backpressure, curried data-last composition, promise unwrapping in pipe, early termination across async work and literal-preserving inference, with deep utilities like `isEqual`, `cloneDeep` and `merge` shared with lodash. lodash is marked as having chain-only laziness, no async iterables, a separate `lodash/fp` entry for curried composition and no promise unwrapping, and the native column has lazy evaluation as ES2025, early termination as synchronous only, and a dash for literal-preserving inference. The last row is worth pausing on: the native column has no literal-preserving inference at all, which is a gap that only exists in TypeScript and which the library treats as a first-class feature.

The build is a TypeScript project with generated output

The package manifest shows a carefully built library. The published artefacts are a CommonJS build at `dist/cjs/index.js`, an ES module build at `dist/esm/index.js`, and type declarations at `dist/types/index.d.ts`, with `typesVersions` mapping for TypeScript 5.5 and above, and `sideEffects` set to false so a bundler can tree-shake. The build script runs cleanup, compilation, webpack and two generator steps, with the compiler producing the three outputs in parallel, and there are separate tsconfig files for the CommonJS, ESM, types and check configurations. The two generator scripts, `generateExtensions.ts` and `generateExports.ts`, produce the extension methods and the export map, which is how the `fx` chaining API and the named exports stay in step with the source. The tests run on Jest, the linting on ESLint, and there is a `type-check/` directory for type-level tests.

Version 2.0 and the older line are different products

The release history has two parallel lines. The v2.0.0 tag is dated 2026-08-08 and the v1.28.0 tag the same day, four hours earlier, with v1.26.0 in February 2026. The package version in the manifest is 2.0.1, so the current line is the 2.x one. The presence of a 1.28 release on the same day as 2.0 suggests the older line got a final maintenance release rather than being abandoned, and the documentation site carries both. The last push to the main branch was on 2026-08-29, and there is no GitHub release history beyond the tags. The repository also has a `website/` directory, which is the documentation site, and a `context7.json` file at the root, which is the metadata format that context-aware documentation tools read, along with an `llms.txt` on the site for the same purpose.

Editorial conclusion

Adopt FxTS if your TypeScript code is full of promise chains and sequential awaits that could be concurrent, since the library's `concurrent` combinator and its async iterable pipelines address exactly that. Do not adopt it in a codebase that only maps over arrays, because plain native code does that better, and note the table in the project documentation says as much. Verify first which major version you take, because 2.0 is a separate line from the 1.28 line, and check the peer TypeScript version, since the type inference is the strongest argument for the library and it is also the thing that will break first if your toolchain is older.

Frequently asked questions

How do I install FxTS?

The package is `@fxts/core` and the install is `npm install @fxts/core`. The published package carries CommonJS and ES module builds plus type declarations, and it is marked as having no side effects so bundlers can tree-shake it.

What does the concurrent function in FxTS do?

It limits how many async operations run at once inside a pipeline, so a set of independent requests completes in the time of the slowest batch rather than the sum of all of them. The documentation example counts words from four Wikipedia pages and shows four seconds unbounded against two seconds at a concurrency of two.

Can FxTS work with LLM streaming responses and Node.js streams?

Yes, because the library is built on the standard iteration protocols. The documentation calls out LLM SDK streams, Node.js streams and paginated APIs as pipelines out of the box, and the same pipe and map functions work over arrays, async iterables and promises.

How does FxTS compare with lodash?

The project documentation publishes a table comparing the two across nine capabilities. FxTS is listed as having lazy evaluation, async iterable pipelines, concurrency control with backpressure, curried data-last composition, promise unwrapping in pipe, early termination across async work and literal-preserving inference, while lodash has chain-only laziness, a separate lodash/fp entry and no async iterables.

What licence is FxTS released under?

Apache License 2.0, with the licence file in the repository root and the copyright attributed to Marpple. The current package version is 2.0.1 and the tags v2.0.0 and v1.28.0 are both dated 2026-08-08.

Official sources

  1. License: Apache-2.0
  2. marpple/FxTS on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/marpple-fxts.svg)](https://hysenlabs.com/projects/marpple-fxts)

Was this useful?