A robust TypeScript implementation of the Result pattern for elegant error handling.
- Type-safe error handling
- Chainable operations
- Nullable value handling
- Rich API for error and success cases
- Zero dependencies
- Full TypeScript support with detailed type information
npm install @kardell/resultimport { Result } from "@kardell/result";
// Success case
const success = Result.of<number, Error>(42);
console.log(success.data); // 42
// Failure case
const failure = Result.failure<string, Error>(
new Error("Something went wrong")
);
console.log(failure.error?.message); // 'Something went wrong'const result = Result.of<number, Error>(42)
.apply((n) => n * 2)
.apply((n) => n.toString());
console.log(result.data); // "84"const userData: string | null = null;
const result = Result.fromNullable(userData)(new Error("User not found"));
result.fold(
(data) => console.log(data),
(error) => console.error(error.message) // Prints: User not found
);const result = Result.of<number, Error>(42)
.apply((n) => n * 2)
.apply((n) => n.toString());
console.log(result.data); // "84"const result = Result.of<number, Error>(42);
const message = result.fold(
(value) => `Success: ${value}`,
(error) => `Error: ${error.message}`
);
console.log(result.data); // "Success: 42"const result = Result.failure<number, Error>(
new Error("Processing failed")
).onFailureReturn(0);
console.log(result.data); // 0// api client
async function fetchUser(id: string): Promise<Result<User, StatusError>> {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
return Result.failure(new Error(`HTTP error: ${response.status}`));
}
const data = await response.json();
return Result.of(data);
} catch (error) {
return Result.failure(
error instanceof Error ? error : new Error("Unknown error")
);
}
}
// api handler
async userHandler(id: string): MyResponseType {
const user = await fetchUser(id);
return user.fold(
(user) => new MyResponseType(200, user),
({status, message}) => new MyResponseType(status, { message })
);
}function processData(input: string): Result<number, Error> {
return Result.fromNullable(input)(new Error("Input is required"))
.apply((str) => parseInt(str, 10))
.failOnCondition((n) => isNaN(n), new Error("Invalid number"));
}of<V, E>(value: V): Result<V, E>- Creates a success resultfailure<V, E>(error: E): Result<V, E>- Creates a failure resultfromNullable<V, E>(value: V | null | undefined): (error: E) => Result<V, E>- Handles nullable values
apply<T>(fn: (v: V) => T): Result<T, E>- Transform success valuesapplyOnFailure(fn: (e: E) => E): Result<V, E>- Transform errorsfold<L, R>(onSuccess: (v: V) => R, onError: (e: E) => L): L | R- Pattern matchingfailOnCondition(predicate: (v: V) => boolean, error: E): Result<V, E>- Conditional failuresonFailureReturn(value: V, filter?: (e: E) => boolean): Result<V, E>- Provide fallback valuespeek(fn: (v: V) => void): Result<V, E>- Side effects for success casesonFailurePeek(fn: (e: E) => void): Result<V, E>- Side effects for failure cases
This project is licensed under the MIT License - see the LICENSE file for details.