01Errors are values
Functions return Result<T, E> instead of throwing. Success carries the value, Failure carries the error, and the type checker makes sure you handle both.
Learn moreA lightweight Result type package
Say goodbye to throw, embrace type-safe results
npm install @praha/byethrow1const parseJson = (text: string) => {2 return JSON.parse(text); // may throw, but the type won't say3};4 5try {6 const data = parseJson('{ "answer": 21 }');7 console.log(data.answer * 2); // data: any8} catch (error) {9 // error: unknown. What could it be?10}Every failure becomes a value. No hidden throws, no forgotten catches, no surprises in production.
Functions return Result<T, E> instead of throwing. Success carries the value, Failure carries the error, and the type checker makes sure you handle both.
Learn more{ type: 'Success', value: 42 }{ type: 'Failure', error: NotFound }No classes, no instanceof, no hidden state. Log it, serialize it, send it across the wire as it is.
Learn moreEvery function accepts both Result and Promise<Result>. There is no second API to learn.
Learn morea failure skips every remaining step
Chain steps with pipe. Each function only runs on success, and a failure flows straight through to the end.
Learn moreEach function is an independent export, so bundlers drop everything you never call.
Learn moreno-throw-in-callbackexpect(result).toBeSuccess()byethrow-docs init claudeA linter plugin, test matchers and documentation for AI assistants keep the whole team on the same patterns.
Learn moreThese snippets are type-checked on every docs build. Hover over any identifier to see what the compiler sees.
Result.fn turns a throwing or async function into one that returns a Result.
import { import Result Result } from '@praha/byethrow';
type type User = {
id: string;
name: string;
}
User = { id: string id : string; name: string name : string };
const const fetchUser: (id: string) => Result.ResultAsync<User, Error> fetchUser = import Result Result .fn<(id: string) => Promise<User>, Error>(options: {
try: (id: string) => Promise<User>;
catch: (error: unknown) => Error;
}): (id: string) => Result.ResultAsync<User, Error> (+3 overloads)
export fn
Wraps a function that may throw and returns a new function that returns a
Result
or
ResultAsync
.
You can use either a custom catch handler or rely on the safe: true option
to assume the function cannot throw.
fn ({
try: (id: string) => Promise<User> try : async (id: string id : string): interface Promise<T>Represents the completion of an asynchronous operation
Promise <type User = {
id: string;
name: string;
}
User > => {
const const response: Response response = await function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> fetch (`/api/users/${id: string id }`);
if (!const response: Response response .Response.ok: booleanThe ok read-only property of the Response interface contains a Boolean stating whether the response was successful (status in the range 200-299) or not.
ok ) throw new var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error (`HTTP ${const response: Response response .Response.status: numberThe status read-only property of the Response interface contains the HTTP status codes of the response.
status }`);
return const response: Response response .Body.json(): Promise<any> json ();
},
catch: (error: unknown) => Error catch : (error: unknown error ) => new var Error: ErrorConstructor
new (message?: string, options?: ErrorOptions) => Error (+1 overload)
Error ('Failed to fetch user', { ErrorOptions.cause?: unknown cause : error: unknown error }),
});
const const result: Result.Result<User, Error> result = await const fetchUser: (id: string) => Result.ResultAsync<User, Error> fetchUser ('u_123');
Install the package and turn your first function into one that returns a Result. It takes about a minute.
npm install @praha/byethrow