Skip to content

feat(result): add unwrapOr, unwrapOrElse, map, and mapFailure#39

Merged
electric-gizzard merged 1 commit into
ByteSliceHQ:mainfrom
coderdan:feat/result-combinators
Jun 28, 2026
Merged

feat(result): add unwrapOr, unwrapOrElse, map, and mapFailure#39
electric-gizzard merged 1 commit into
ByteSliceHQ:mainfrom
coderdan:feat/result-combinators

Conversation

@coderdan

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #37 (unwrap/expect). Adds four more Rust-inspired combinators to @byteslice/result, all as free functions consistent with the package's existing functional surface:

  • unwrapOr(result, fallback) — returns the success data, or an eager fallback value. Never throws.
  • unwrapOrElse(result, fn) — returns the success data, or computes a fallback from the failure (fn is only invoked on failure). Never throws.
  • map(result, fn) — transforms the success data (Result<S, F>Result<U, F>), passing a failure through untouched.
  • mapFailure(result, fn) — transforms the failure (Result<S, F>Result<S, G>), passing a success through untouched.

Design notes

  • Total extractors don't throw. Unlike unwrap/expect, the unwrapOr* pair always returns a value — fitting TS's preference for not throwing on expected paths. They correctly return falsy success data (e.g. 0, '') rather than the fallback, since they branch on the success/failure discriminant, not truthiness.
  • unwrapOrElse and mapFailure receive the full failure (F), not an extracted Error — mirroring Rust's E and giving callers access to custom-failure fields. (unwrap/expect extract an Error only because they throw.)
  • map is synchronous and non-catching, matching Rust's infallible closure. If a transform can fail, withResult is the right tool — called out in the docs.
  • mapFailure's mapped failure is constrained G extends FailureOption, so you can't map to an invalid failure shape.

Testing

  • 16 new unit tests (27 total), covering success/failure paths, falsy-data handling, lazy-callback non-invocation, and custom failures.
  • bun test, biome ci, cspell, and tsup build all pass.

Changeset

Included a minor changeset. Also added combinator/combinators to the cspell word list.

Adds Rust-inspired combinators to complement unwrap/expect:
- unwrapOr / unwrapOrElse: total, non-throwing extractors that return a
  fallback value (eager) or compute one from the failure (lazy).
- map / mapFailure: transform the success data or the failure while
  passing the other state through untouched.
@changeset-bot

changeset-bot Bot commented Jun 28, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: dc78c5e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@byteslice/result Minor
@byteslice/events Patch
@byteslice/playground Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@electric-gizzard electric-gizzard left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderdan your "Rust zealot[ry]" is showing 🦀

Thank you for contributing!

@electric-gizzard electric-gizzard merged commit 97c41db into ByteSliceHQ:main Jun 28, 2026
2 checks passed
@coderdan

Copy link
Copy Markdown
Contributor Author

@coderdan your "Rust zealot[ry]" is showing 🦀

Thank you for contributing!

It's a sickness, what can I say! Thanks for the quick approval!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants