Try-free result handling for TypeScript
Try-free result handling for TypeScript
dethrown helps you handle errors in TypeScript projects without relying ontry/catch. It provides helpers ok and err for representing success and
failure. It also includes a chain help that allows for lightweight functional
handling of results.
``typescript
import { err, ok, chain } from "dethrown";
function divide(numerator: number, denominator: number) {
if (denominator === 0) {
return err("Divide by zero error");
}
return ok(numerator / denominator);
}
const finalValue = chain(divide(12, 3))
.inspect(console.log)
.ifOK((value) => divide(value, 2))
.ifErr((error) => err(Something went wrong: ${error}))
.unwrap();
console.log(finalValue);
`
- ok
- err
- unwrap
- tryCatch
- tryCatchAsync
- chain
- chain.inspect
- chain.inspectAsync
- chain.map
- chain.mapAsync
- chain.mapErr
- chain.mapErrAsync
- chain.ifOK
- chain.ifOKAsync
- chain.ifErr
- chain.ifErrAsync
- chain.result
- chain.unwrap
`typescript`
export function ok
Creates an OK value representing a successful result.
#### Example
`typescript
import { ok } from "dethrown";
const result = ok(12);
console.log(result.ok); // true
console.log(result.value); // 12
`
`typescript`
export function err(error: E): Err
Creates an Err value respresenting a failure.
Err will often be used to wrap exceptions, but it's not required.
#### Example
`typescript
import { err } from "dethrown";
const result = err("It broke");
console.log(result.ok); // false
console.log(result.err); // It broke
`
`typescript`
export function unwrap
Returns a value of type T or throws an error.
#### Example
`typescript
import { ok, err, unwrap } from "dethrown";
const good = ok("Good");
console.log(unwrap(good)); // Good
const bad = err("So bad");
// will throw
console.log(unwrap(bad));
`
`typescript`
export function tryCatch
tryCatch takes in a function, calls it, and returns a result containing the
return value of the function or any exceptions thrown.
#### Example
`typescript
import { tryCatch } from "dethrown";
const result = tryCatch(() => {
return mightThrow();
});
`
`typescript`
export async function tryCatch
tryCatchAsync takes in an async function, calls it, and returns a result
containing the return value of the function or any exceptions thrown.
#### Example
`typescript
import { tryCatchAsync } from "dethrown";
const result = tryCatchAsync(async() => {
return await mightThrow();
});
`
`typescript`
export function chain
Chain takes a value or a result and allows for chained calls against it.
Chain itself always returns a ResultChain, but chained calls may return aResultChain or AsyncResultChain depending on if the chained function isAsyncResultChain
async or not. Once an async function is called, the remaining calls always
return an .
#### Example
`typescriptHello ${name}!
const chainResult = chain("Frank")
.map((name) => )${message} How are you?
.map((message) => )
.result();
const chainResult = chain(ok("Frank"))
.map((name) => Hello ${name}!)${message} How are you?
.map((message) => )
.result();
const asyncChainResult = await chain(ok("Frank"))
.mapAsync((name) => find(name))
.mapAsync((user) => updateUser({ name: "Frank Smith" }))
.result();
`
`typescript`
chain.inspect(fn: (r: Result
asyncChain.inspect(fn: (r: Result
inspect calls the given function on the current result in the chain andResult
returns a chain with the same . It's useful for cases like logging a
value in a chain.
#### Example
`typescript${name} Smith
chain("Frank")
.map((firstName) => )`
.inspect((fullName) => console.log(fullName))
.result();
`typescript`
chain.inspectAsync(fn: (r: Result
asyncChain.inspectAsync(fn: (r: Result
inspectAsync is identical to inspect except that it takes an async functionAsyncResultChain
and results in an .
#### Example
`typescript${firstName} Smith
await chain("Frank")
.map((firstName) => )`
.inspectAsync(async (fullName) => await auditLog(fullName))
.result();
`typescript`
chain.map(fn: (t: T) => U): ResultChain;
asyncChain.map(fn: (t: T) => U): AsyncResultChain;
map converts one type of OK value into another. If the current result inOK
the chain is , calls fn with the current result value as an argument.
Otherwise, passes the current result along the chain.
#### Example
`typescript${name} Smith
chain("Frank")
.map((firstName) => )`
result();
`typescript`
chain.mapAsync(fn: (t: T) => Promise): AsyncResultChain;
asyncChain.mapAsync(fn: (t: T) => Promise): AsyncResultChain;
mapAsync converts one type of OK value into another, just like map, butOK
allows the conversion function to be async. If the current result in the chain
is , calls the given async fn with the current result value as an argument.
Otherwise, passes the current result along the chain.
#### Example
`typescript`
await chain(username)
.mapAsync(async (username) => await loadUser(username))
.result();
`typescript`
chain.mapErr(fn: (e: E) => S): ResultChain
asyncChain.mapErr(fn: (e: E) => S): AsyncResultChain
mapErr converts one type of Err value into another. If the current resultErr
in the chain is , calls the given fn with the current error value as an
argument. Otherwise, passes the current result along the chain.
#### Example
`typescriptCause: ${error}
chain(err("It broke"))
.mapErr((error) => )`
.result();
`typescript`
chain.mapErrAsync(fn: (e: E) => Promise): AsyncResultChain
asyncChain.mapErrAsync(fn: (e: E) => Promise): AsyncResultChain
mapErrAsync converts one type of Err value into another, just like mapErr,Err
but allows the conversion function to be async. If the current result in the
chain is , calls the given async fn with the current error value as an
argument. Otherwise, passes the current result along the chain.
#### Example
`typescript`
await chain(username)
.ifOKAsync((value) => await loadUserByUsername(value))
.mapErrAsync(async (error) => await loadUserByEmail(r.value))
.result();
`typescript`
chain.ifOK(fn: (r: T) => Result): ResultChain;
asyncChain.ifOK(fn: (r: T) => Result): ResultChain;
If the current result in the chain is OK, calls the given fn with the
current value as an argument. Otherwise, passes the current result along the
chain.
#### Example
`typescript`
chain(username)
.ifOK((value) => validateUsername(value))
.result();
`typescript`
chain.ifOKAsync(fn: (r: T) => Promise
asyncChain.ifOKAsync(fn: (r: T) => Promise
If the current result in the chain is OK, calls the given async fn with the
current value as an argument. Otherwise, passes the current result along the
chain.
#### Example
`typescript`
await chain(username)
.ifOKAsync((value) => await loadUser(value))
.result();
`typescript`
chain.ifErr(fn: (r: E) => Result
asyncChain.ifErr(fn: (r: E) => Result
If the current result in the chain is Err, calls the given fn with the
current error value as an argument. Otherwise, passes the current result along
the chain.
#### Example
`typescript`
chain(divisor)
.ifOK((value) => divide(12, value))
.ifErr((error) => ok(0))
.result();
`typescript`
chain.ifErrAsync(fn: (r: E) => Promise
asyncChain.ifErrAsync(fn: (r: E) => Promise
If the current result in the chain is Err, calls the given async fn with
the current error value as an argument. Otherwise, passes the current result
along the chain.
#### Example
`typescript`
await chain(newPlan)
.ifOKAsync((r) => await setPlan(r.value))
.ifErrAsync((r) => {
return err({
message: r.err.message,
planOptions: await listPlans()
});
})
.result();
`typescript`
chain.result(): Result
asyncChain.result: Promise
Returns the last result value on the chain. If it's an async chain, returns
a promise that will resolve to the last result once all promises in the chain
have completed.
#### Example
`typescript`
// returns a Result
chain(userId)
.map(loadUser)
.result();
`typescript`
chain.unwrap(): T;
asyncChain.unwrap(): Promise
Like unwrap, either returns the success value or throws the error
value for the last result on the chain.
#### Example
`typescript``
// returns the user or throws if the user wasn't found
chain(userId)
.map(loadUser)
.unwrap();
MIT. See LICENSE for details.