next-result v0.1.1
next-result
A rust-inspired Result type for Next.js; can be used anywhere.
Features
- đĒļ Lightweight - Tiny implementation with zero dependencies
- đĒ Type-Safe - Full TypeScript support with type inference
- đ¯ Server Action Ready - Perfect for Next.js Server Actions
- đ Promise Support - Built-in utilities for async operations
Problem
When using server actions, you need to handle errors. You could throw an Error from the server action and have it be handled by the client.
But, Next.js masks the actual error message in production, so we can't do that!
Solution
This library provides a Result type that can be used to return errors from server actions and have them be handled by the client.
Installation
npm install next-result
# or
yarn add next-result
# or
pnpm add next-result
Basic Usage
The Result type provides a type-safe way to handle operations that might fail:
import { Result, Ok, Err } from "next-result";
function divide(a: number, b: number): Result<number> {
if (b === 0) {
return Err("Cannot divide by zero");
}
return Ok(a / b);
}
// Success case
const result1 = divide(10, 2);
if (result1.ok) {
console.log(result1.value); // 5
}
// Error case
const result2 = divide(10, 0);
if (!result2.ok) {
console.log(result2.error); // "Cannot divide by zero"
}
Next.js Server Action Example
Perfect for handling server action results with TanStack Query:
// app/actions.ts
"use server";
import { Ok, Err } from "next-result";
interface User {
id: string;
name: string;
}
export async function createUser(name: string) {
try {
// Your database operation here
const user = await db.users.create({ name });
return Ok({ id: user.id, name: user.name });
} catch (error) {
return Err("Failed to create user");
}
}
// app/components/create-user.tsx
"use client";
import { unwrapPromise } from "next-result";
import { useMutation } from "@tanstack/react-query";
import { createUser } from "../actions";
export function CreateUser() {
const { mutate, isError, isSuccess, isPending, error, data } = useMutation({
mutationFn: (name: string) => unwrapPromise(createUser(name)),
onSuccess: (data) => {
// do something
// show a success toast
},
onError: (error) => {
// do something
// show an error toast
},
});
return (
<form
onSubmit={(e) => {
e.preventDefault();
mutate("John Doe");
}}
>
{isError ? <div>Error: {error.message}</div> : null}
{isSuccess ? <div>Created user: {data.name}</div> : null}
<button type="submit" disabled={isPending}>
{isPending ? "Creating user..." : "Create User"}
</button>
</form>
);
}
API Reference
Types
Result
The main type representing either success or failure.
type Result<T> = Ok<T> | Err;
Ok
Represents a successful result containing a value.
type Ok<T> = {
ok: true;
value: T;
};
Err
Represents an error result containing an error message.
type Err = {
ok: false;
error: string;
};
Option
Represents an optional value that can be either a value or null.
type Option<T> = T | null;
PromiseResult
A promise that resolves to a Result.
type PromiseResult<T> = Promise<Result<T>>;
Constructors
Ok
Creates a successful result containing a value.
const success = Ok(42);
// { ok: true, value: 42 }
Err
Creates an error result with an error message.
const error = Err("Something went wrong");
// { ok: false, error: "Something went wrong" }
Type Guards
isOk
Type guard to check if a result is successful.
if (isOk(result)) {
// result.value is accessible here
}
isErr
Type guard to check if a result is an error.
if (isErr(result)) {
// result.error is accessible here
}
Value Extractors
unwrap
Extracts the value from a successful result or throws the error.
const value = unwrap(Ok(42)); // 42
// unwrap(Err("error")); // throws Error("error")
unwrapOrDefault
Extracts the value or returns a default value.
const value = unwrapOrDefault(Ok(42), 0); // 42
const def = unwrapOrDefault(Err("error"), 0); // 0
optionOk
Extracts the value from a successful result or returns null.
const value = optionOk(Ok(42)); // 42
const none = optionOk(Err("error")); // null
optionErr
Extracts the error message from an error result or returns null.
const error = optionErr(Err("error")); // "error"
const none = optionErr(Ok(42)); // null
For Async Operations
unwrapPromise
Awaits a promise result and unwraps it.
const value = await unwrapPromise(Promise.resolve(Ok(42))); // 42
// throws if the result is an error
unwrapPromiseOrDefault
Awaits a promise result and unwraps it or returns a default value.
async function testOK() {
// ... some async operations
return Ok(42);
}
async function testErr() {
// ... some async operations
return Err("error");
}
const value = await unwrapPromiseOrDefault(testOK(), 0); // 42
const def = await unwrapPromiseOrDefault(testErr(), 0); // 0
License
MIT