Zygos ↔ Neverthrow Interoperability
Real compatibility data. No guesswork. Analyzed against Neverthrow 8.2.0.
TL;DR
100% API compatible. Zygos Result is a drop-in replacement for Neverthrow with identical API and behavior.
| Metric | Value |
|---|---|
| Result API | 100% compatible |
| ResultAsync API | 100% compatible |
| Bundle Size | 2.6x smaller (~774 B vs ~1.96 kB) |
| Migration Effort | Import change only |
Change your import from neverthrow to pithos/zygos/result/result and you're done. Zero code changes required.
About Zygos Result
Zygos Result is a micro implementation of Neverthrow's Result type that is:
- 2.6x smaller (~774 B vs ~1.96 kB) than Neverthrow 8.2.0
- 100% API compatible - can be seamlessly replaced without code changes
- Zero
anytypes for better type safety
// Just swap your import
// Before
import { ok, err, Result, ResultAsync } from "neverthrow";
// After
import { ok, err, Result } from "pithos/zygos/result/result";
import { ResultAsync } from "pithos/zygos/result/result-async";
// Your existing code works as-is
Full API Compatibility
Click to expand each category and see the supported features:
Result Constructors (100%)2/2
ok(value), err(error)
import { ok, err, Result } from "pithos/zygos/result/result";
const success: Result<number, string> = ok(42);
const failure: Result<number, string> = err("Something went wrong");
Result Methods (100%)7/7
.isOk(), .isErr(), .map(), .mapErr(), .andThen(), .unwrapOr(), .match()
const result = ok(5)
.map(x => x * 2) // Transform success value
.mapErr(e => `Error: ${e}`) // Transform error value
.andThen(x => x > 0 ? ok(x) : err("negative")); // Chain operations
const value = result.unwrapOr(0); // Get value or default
const message = result.match(
value => `Success: ${value}`,
error => `Error: ${error}`
);
Result Static Methods (100%)2/2
Result.fromThrowable(), Result.combine()
// Wrap throwing functions
const safeParse = Result.fromThrowable(
JSON.parse,
(error) => `Parse error: ${error}`
);
const result = safeParse('{"valid": "json"}'); // Ok({valid: "json"})
const error = safeParse('invalid'); // Err("Parse error: ...")
// Combine multiple Results
const combined = Result.combine([ok(1), ok(2), ok(3)]); // Ok([1, 2, 3])
const withError = Result.combine([ok(1), err("fail"), ok(3)]); // Err("fail")
ResultAsync Constructors (100%)2/2
okAsync(), errAsync()
import { okAsync, errAsync, ResultAsync } from "pithos/zygos/result/result-async";
const asyncSuccess = okAsync(Promise.resolve(42));
const asyncError = errAsync("network error");
ResultAsync Methods (100%)7/7
.map(), .mapErr(), .andThen(), .unwrapOr(), .match(), .orElse(), .then()
const result = await okAsync(Promise.resolve(5))
.map(x => x * 2)
.andThen(x => okAsync(Promise.resolve(x.toString())));
// Pattern matching
const message = await result.match(
value => `Success: ${value}`,
error => `Error: ${error}`
);
// Fallback on error
const withFallback = await errAsync("error")
.orElse(() => okAsync("fallback"));
ResultAsync Static Methods (100%)4/4
ResultAsync.fromPromise(), ResultAsync.fromSafePromise(), ResultAsync.fromThrowable(), ResultAsync.combine()
// From potentially failing Promise
const result = ResultAsync.fromPromise(
fetch('/api/data'),
(error) => `Fetch failed: ${error}`
);
// From safe Promise (won't reject)
const safe = ResultAsync.fromSafePromise(Promise.resolve(42));
// Wrap async throwing functions
const safeFetch = ResultAsync.fromThrowable(
async (url: string) => {
const res = await fetch(url);
return res.json();
},
(error) => `Request failed: ${error}`
);
// Combine multiple async Results
const combined = ResultAsync.combine([
okAsync(1),
okAsync(2),
okAsync(3)
]); // Ok([1, 2, 3])
safeTry (100%)1/1
safeTry()import { safeTry, ok, err } from "pithos/zygos/result/result";
// With generator function
const result = safeTry(function* () {
yield err("validation failed");
return ok(42);
});
// With direct function
const direct = safeTry(() => ok(42));
What Zygos adds
Beyond Neverthrow compatibility, Zygos brings unique features:
| Feature | Description |
|---|---|
2.6x smaller | ~774 B vs ~1.96 kB |
Zero any Types | Better type safety with unknown types |
fp-ts Bridges | Convert to/from Option and Either |
safeAsyncTry | Simplified async error handling |
combineWithAllErrors | Collect all errors instead of stopping at first |
fp-ts Interoperability
Zygos provides bridges to convert between Result and fp-ts types:
import {
fromOption,
fromEither,
toEither,
ok,
err
} from "pithos/zygos/result/result";
// Option → Result
const someOption = { _tag: "Some", value: 42 };
const noneOption = { _tag: "None" };
const fromSome = fromOption(() => "No value")(someOption); // Ok(42)
const fromNone = fromOption(() => "No value")(noneOption); // Err("No value")
// Either → Result
const rightEither = { _tag: "Right", right: 42 };
const leftEither = { _tag: "Left", left: "error" };
const fromRight = fromEither(rightEither); // Ok(42)
const fromLeft = fromEither(leftEither); // Err("error")
// Result → Either
const okResult = ok(42);
const errResult = err("error");
const toRight = toEither(okResult); // { _tag: "Right", right: 42 }
const toLeft = toEither(errResult); // { _tag: "Left", left: "error" }
safeAsyncTry
Simplified async error handling without generators:
import { safeAsyncTry } from "pithos/zygos/result/result";
const fetchUser = async (id: string) => {
const response = await fetch(`/api/users/${id}`);
return response.json();
};
const result = await safeAsyncTry(() => fetchUser("123"));
if (result.isOk()) {
console.log(result.value); // User data
} else {
console.log(result.error); // Error details
}
combineWithAllErrors
Collect all errors instead of stopping at the first one:
import { ResultAsync, okAsync, errAsync } from "pithos/zygos/result/result-async";
const results = [
okAsync(1),
errAsync("error1"),
okAsync(3),
errAsync("error2")
];
const combined = ResultAsync.combineWithAllErrors(results);
const resolved = await combined;
// Err(["error1", "error2"]) - collects ALL errors
Ready to migrate? The complete step-by-step migration guide is in the Zygos module documentation: install, swap imports, and start using additional features. Go to migration guide →
Not sure which library fits your use case? See the comparison overview.
Why choose Zygos over Neverthrow?
| Aspect | Zygos | Neverthrow |
|---|---|---|
| Bundle Size | ~774 B (2.6x smaller) | ~1.96 kB |
| Type Safety | Zero any types | Uses any in some places |
| fp-ts Bridges | fromOption, fromEither, toEither | ![]() |
| safeAsyncTry | Simplified async handling | ![]() |
| combineWithAllErrors | ![]() | ![]() |
| API Compatibility | 100% drop-in replacement | - |
If you're already using Neverthrow, switching to Zygos is straightforward: same API, smaller bundle, better types, and additional features. Just change your imports.
Related
- Zygos vs Neverthrow — Full comparison: philosophy, API, migration
- Kanon ↔ Zod Interoperability — Another migration compatibility story
- Equivalence Table — Full library equivalence across all modules
- Zygos Module Guide — Full module documentation
Zero
fp-ts Bridges
safeAsyncTry
combineWithAllErrors