unwrapit provides a way to handle errors in JS/TS gracefully and intuitively. Inspired by Rust's Result type, it lets you wrap functions, promises, and values so that errors are captured as values instead of thrown exceptions.
The docs source lives in docs and can be previewed locally:
pnpm run docs:devThe legacy GitBook site is still available at https://musicq.gitbook.io/unwrapit/.
npm i unwrapitimport { wrap } from 'unwrapit'
// Wrap a function that might throw
const safeParse = wrap(JSON.parse)
const result = safeParse('{"name": "unwrapit"}')
if (result.ok) {
console.log(result.value) // { name: 'unwrapit' }
} else {
console.error(result.error)
}import { wrap } from 'unwrapit'
const safeFetch = wrap(fetch)
const result = await safeFetch('https://api.example.com/data')
const response = result.unwrap()
const data = await response.json()The core function. It wraps functions, promises, or plain values and returns a Result type that is either Ok or Err.
Wrapping a function returns a new function with the same signature, but the return value is wrapped in a Result.
import { wrap } from 'unwrapit'
// Sync function
const safeParse = wrap(JSON.parse)
const result = safeParse('invalid json') // Result<any, unknown>
// Async function
const safeFetch = wrap(fetch)
const result = await safeFetch('https://example.com') // Result<Response, unknown>import { wrap } from 'unwrapit'
const promise = fetch('https://example.com')
const result = await wrap(promise) // Result<Response, unknown>import { wrap } from 'unwrapit'
const result = wrap(42) // Result<number, never>Call wrap() with no arguments to get a curried version where you can specify the error type:
import { wrap } from 'unwrapit'
const safeParse = wrap<SyntaxError>()(JSON.parse)
const result = safeParse('invalid') // Result<any, SyntaxError>Create Result values directly.
import { ok, err } from 'unwrapit'
const success = ok(42) // Result<number, never>
const failure = err('oops') // Result<unknown, string>Every Result value (whether from wrap, ok, or err) has the following methods:
Extract the contained value. Panics if the result is Err.
ok(1).unwrap() // 1
err('x').unwrap() // panicsYou can pass WrapOption to control panic behavior:
result.unwrap({ panic: true, exitCode: 2 })Return the contained value, or a default if it is Err.
ok(1).unwrapOr(0) // 1
err('x').unwrapOr(0) // 0Return the contained value, or compute a fallback from the error.
ok(1).unwrapOrElse(e => 0) // 1
err('hello').unwrapOrElse(e => e.length) // 5Extract the contained value. Panics with a custom error message if the result is Err.
ok(1).expect('should not fail') // 1
err('x').expect('parsing failed') // panics with "parsing failed"Transform the error value, leaving Ok untouched.
err('not found').mapErr(e => new Error(e))
// Err<Error, unknown>
ok(1).mapErr(e => new Error(String(e)))
// Ok<number> (unchanged)Pattern match on Ok and Err.
const result = ok(1).match({
Ok: v => v + 1,
Err: e => 0,
}) // 2You can also provide only one branch:
ok(1).match({ Ok: v => v * 2 }) // 2
err('x').match({ Err: e => e.length }) // 1Set global configuration for unwrapit.
import { defineUnwrapitConfig } from 'unwrapit'
defineUnwrapitConfig({
// Exit the program on panic (default: false)
// In browser: throws an error. In Node: calls process.exit()
panic: true,
// Custom panic function
panicFn: (msg, opts) => {
reportError(msg)
throw new Error(String(msg))
},
})Re-exported from panicit. Throws a panic error.
import { panic } from 'unwrapit'
panic('something went wrong')unwrapit provides a toWrap RxJS operator that converts observable errors into Result values instead of terminating the stream.
import { from, map } from 'rxjs'
import { toWrap } from 'unwrapit/rxjs'
from([1, 2, 3]).pipe(
map(x => {
if (x % 2 === 0) throw new Error(`${x} is even`)
return x
}),
toWrap()
).subscribe(result => {
if (!result.ok) {
console.error(result.error)
return
}
console.log(result.value)
})Install rxjs as a peer dependency to use this feature:
npm i rxjsMIT