new generic Operator ***SelectMany*** for capturing concatMap, switchMap, mergeMap and exhaustMap #7572
hansschenker
started this conversation in
Ideas / Feature request
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Proposal: Add
selectMany
(Rx.NET-style) as a unified map+flatten operatorTL;DR
Introduce
selectMany(project, options?)
as a small, explicit wrapper over the existing map+flatten family. It offers a single, discoverable entry point for “Observable of Observables” with a readable strategy parameter:sequential
→concatMap
(preserve order)concurrent
→mergeMap
(optionalconcurrency
)latest-wins
→switchMap
(cancel previous)first-wins
→exhaustMap
(ignore new until current completes)This mirrors Rx.NET’s SelectMany naming and reduces cognitive overhead without introducing any new semantics.
Motivation
Today, users must choose among four operator names for the same pattern: project to an inner stream and then flatten. For many, especially newcomers, the first step is “how do I flatten?” not “which of the four map+flatten names do I recall?”.
A single, ergonomic entry point—
selectMany
—lets developers write what they mean, then pick the desired flattening behavior via an option. It also provides a familiar bridge for Rx.NET users who instinctively look for SelectMany.Benefits:
strategy: 'latest-wins'
).API (strawman)
Drop-in equivalences
Examples
Users → Todos; latest selection cancels previous:
Bounded concurrency:
Design Notes
No new behavior:
selectMany
simply delegates toconcatMap
/mergeMap
/switchMap
/exhaustMap
.Naming: Uses the widely recognized Rx.NET term SelectMany, which matches the mental model “select many results from each value.”
Options scope:
strategy
(andconcurrency
when'concurrent'
).filter
/map
after flatten to keep common pipelines compact. If API surface is a concern, we can omit these extras from core.Type safety:
concurrency
valid only with'concurrent'
.Bundle & Tree-shaking
One concern: a single file that imports all four flatteners could bloat bundles.
Mitigations (choose any or both):
Keep
selectMany
in its own file with/* @__PURE__ */
annotations and rely on DCE.Offer per-strategy aliases in separate entry points (tree-shakeable):
selectManySequential
,selectManyConcurrent
,selectManyLatestWins
,selectManyFirstWins
.If bundle size is still a concern, we can land the minimal API (no post-flatten options) to keep the file small.
Alternatives Considered
flatMap
: Historically an alias tomergeMap
; doesn’t solve discoverability for the other strategies.chain
/bind
/flatSelect
: Functional but less familiar to the Rx community thanSelectMany
.Backward Compatibility
Implementation Sketch (thin wrapper)
Marble tests would mirror each underlying operator’s semantics (ordering, cancellation, concurrency), plus a typed test ensuring
concurrency
is gated to'concurrent'
.Open Questions for Maintainers
filter
/map
?selectMany
live on the same page as the four flatteners, or on its own page with cross-links?Next Steps
If there’s interest, I can open a PR with:
Thanks for considering! Happy to iterate based on feedback.
Beta Was this translation helpful? Give feedback.
All reactions