@monitext/ncatch
Type-safe, Go-style error handling for synchronous and asynchronous JavaScript and TypeScript code.
ncatch helps you replace ad-hoc try/catch blocks with small tuple-based helpers:
- Success:
[null, data] - Failure:
[Error, null]
Install
bash
pnpm add @monitext/ncatchWhy
When you want explicit error handling without exceptions bubbling through your code, ncatch gives you a small set of helpers that:
- work with sync and async code
- normalize unknown thrown values into real
Errorinstances - preserve parameter and return types
- keep success and failure handling consistent
Quick Start
ts
import { tryCatch } from "@monitext/ncatch"
const [err, data] = tryCatch(() => JSON.parse('{"ok":true}'))
if (err) {
console.error(err.message)
} else {
console.log(data.ok)
}Async code works the same way:
ts
import { tryCatch } from "@monitext/ncatch"
const [err, user] = await tryCatch(async () => {
return { id: "u_123", name: "Ada" }
})
if (err) {
console.error(err.message)
} else {
console.log(user.name)
}API
tryCatch
Safely executes:
- a synchronous function
- an asynchronous function
- a
Promise
ts
import { tryCatch } from "@monitext/ncatch"
const [syncErr, syncData] = tryCatch(() => 42)
const [asyncErr, asyncData] = await tryCatch(async () => 42)
const [promiseErr, promiseData] = await tryCatch(Promise.resolve(42))trySync
Use when you want a sync-only helper.
ts
import { trySync } from "@monitext/ncatch"
const [err, data] = trySync(() => {
if (Math.random() > 0.5) throw new Error("boom")
return "ok"
})tryAsync
Use when you want an async-only helper.
ts
import { tryAsync } from "@monitext/ncatch"
const [err, data] = await tryAsync(async () => {
return { ok: true }
})createSafeExecutor
Wraps a function and returns a new function that never throws.
ts
import { createSafeExecutor } from "@monitext/ncatch"
const safeDivide = createSafeExecutor((a: number, b: number) => {
if (b === 0) throw new Error("Cannot divide by zero")
return a / b
})
const [err, result] = safeDivide(10, 2)It also works for async functions:
ts
import { createSafeExecutor } from "@monitext/ncatch"
const safeFetchUser = createSafeExecutor(async (id: string) => {
return { id, active: true }
})
const [err, user] = await safeFetchUser("user_1")createResult
Creates a normalized result tuple in the shape [error, data, meta].
ts
import { createResult } from "@monitext/ncatch"
const result = createResult({
error: null,
data: { id: "evt_1" },
meta: { source: "cache" }
})
// [null, { id: "evt_1" }, { source: "cache" }]Non-Error values are converted into an Error instance automatically.
ts
import { createResult } from "@monitext/ncatch"
const [err] = createResult({ error: "something failed" })
console.log(err instanceof Error) // truecreateError
Normalizes unknown thrown values into a real Error.
ts
import { createError } from "@monitext/ncatch"
const err = createError("raw failure")
console.log(err.message)Common Pattern
ts
import { tryCatch } from "@monitext/ncatch"
export async function loadProfile(id: string) {
const [err, profile] = await tryCatch(async () => {
return { id, name: "Lin" }
})
if (err) {
return {
ok: false as const,
message: err.message,
}
}
return {
ok: true as const,
profile,
}
}Notes
- Thrown strings and other non-
Errorvalues are converted intoErrorinstances. tryCatchreturns a promise only when the input is async.createSafeExecutorpreserves the wrapped function's parameter list.
License
Apache-2.0