Skip to main content

Frequently Asked Questions

Find answers to common questions about NeverThrow, Result types, and error handling patterns.

General Questions

Although the package is called neverthrow, don’t take this literally. The name encourages developers to think more carefully about the ergonomics and usage of their software.Throwing and catching exceptions is very similar to using goto statements - it makes reasoning about programs harder. Additionally, by using throw you make the assumption that the caller of your function is implementing catch, which is a known source of errors.Example scenario: One developer throws an error, and another developer uses the function without prior knowledge that it will throw. An edge case has been left unhandled, leading to unhappy users.That said, there are definitely legitimate use cases for throwing in your program - just far fewer than you might think.
A Result type represents either success (Ok) or failure (Err). This makes it impossible to ignore errors because the error is explicitly part of the type signature.Instead of:
You write:
The caller must handle the error case explicitly.
try/catch:
  • Errors are not visible in type signatures
  • Easy to forget to handle errors
  • Stack traces can be lost
  • Control flow is implicit
NeverThrow:
  • Errors are explicit in type signatures
  • Compiler forces error handling
  • Composable error handling with map, andThen, etc.
  • Control flow is explicit and easier to reason about
NeverThrow does not depend on any runtime-specific features. It works with:
  • Node.js (v18+)
  • Browsers (all modern browsers)
  • Deno
  • Bun
  • Any JavaScript runtime that supports ES6
The engines field in package.json specifies Node.js v18+ and npm v11+ primarily for maintaining a consistent development environment, not as a hard runtime requirement.
Yes! NeverThrow works with plain JavaScript. However, you lose the type safety benefits that make Result types powerful. The library will still provide the same API, but TypeScript’s compiler won’t help catch errors.For maximum benefit, we strongly recommend using TypeScript.

Working with Results

Use Result for synchronous operations:
Use ResultAsync for asynchronous operations:
Note: ResultAsync is thenable and behaves like a native Promise, but with additional methods.
Use Result.fromThrowable or ResultAsync.fromThrowable:
map transforms the Ok value, returning a new Result:
andThen is for chaining operations that can fail:
Use map when the transformation cannot fail, and andThen when it can.
Use Result.combine or Result.combineWithAllErrors:combine (short-circuits on first error):
combineWithAllErrors (collects all errors):
safeTry reduces boilerplate when working with multiple Results in sequence. It uses generator functions to implicitly return early on errors:Without safeTry:
With safeTry:
As of v8.1.0, you don’t need to call .safeUnwrap() anymore.

Advanced Patterns

Use andTee for Ok values or orTee for Err values:Logging success without changing the Result:
Logging errors without changing the Result:
Both methods let the original Result pass through regardless of the callback’s result.
andTee: Side effects, errors are ignored:
andThrough: Validation, errors propagate:
Use asyncAndThen or asyncMap:
Yes! Use ResultAsync.fromPromise:

Testing

You have several options:Option 1: Use _unsafeUnwrap (recommended for tests):
Option 2: Compare Results directly:
Option 3: Check properties:
It’s recommended to use a more lenient setting for test files since _unsafeUnwrap is legitimate in tests:

Migration and Integration

Migrate incrementally:
  1. Start with new code: Write all new functions using Results
  2. Wrap throwing functions: Use Result.fromThrowable for existing functions
  3. Update critical paths: Convert error-prone code paths first
  4. Add ESLint plugin: Enforce Result handling in new code
  5. Gradually refactor: Convert remaining code over time
Example bridge function:
Yes! Results work great with web frameworks:
Results work well with UI frameworks:React example:

Troubleshooting

Make sure you’ve installed the package:
And that your TypeScript configuration includes the correct module resolution:
Most type issues can be resolved by:
  1. Updating TypeScript: NeverThrow requires TypeScript 4.7+
  2. Checking return types: Ensure functions explicitly return Result<T, E>
  3. Using explicit type annotations when needed:

Additional Resources