A TypeScript utility for handling success (Ok) and failure (Err) cases in a structured and type-safe manner.
npm install result-libraryThe Result library is a TypeScript utility that provides a structured way to handle success (Ok) and failure (Err) cases in your application. It is inspired by functional programming patterns and languages like Rust, enabling robust error handling without relying on exceptions.
- Type Safety: Explicitly handle Ok and Err cases with strong TypeScript typings.
- Convenient API: Simplifies handling success and error scenarios with intuitive methods.
- Improved Error Handling: Avoid unexpected runtime errors with structured control flows.
- Reusable Components: Easily integrate into any TypeScript project.
``bash`
npm install result-library
`typescript
import { Err, Ok, type Result } from 'result-library'
function maybeNumber(success: boolean): Result
if(success) return new Ok(1)
return new Err("it failed")
}
maybeNumber(true).unwrap() // 1
maybeNumber(false).unwrap_err() // "it failed"
`
To create Ok and Err results, use the ResultBuilder interface.
`typescript
import { ResultBuilder } from 'result-library';
const { Ok, Err } = ResultBuilder
const success = Ok("Operation was successful");
const failure = Err("An error occurred");
`
`typescript
if (success.is_ok()) {
console.log("Success:", success.unwrap());
} else {
console.error("Error:", success.err());
}
if (failure.is_err()) {
console.error("Failure:", failure.unwrap_err());
}
`
`typescript
function divide(a: number, b: number) {
const { Ok, Err } = ResultBuilder
if (b === 0) {
return Err("Division by zero is not allowed");
}
return Ok(a / b);
}
const result = divide(10, 2);
if (result.is_ok()) {
console.log("Result:", result.unwrap());
} else {
console.error("Error:", result.unwrap_err());
}
`
You can define explicit types for better type safety.
`typescript
const { Ok, Err } = ResultBuilder
const result = Ok(42);
const error = Err("Something went wrong");
if (result.is_ok()) {
console.log(result.unwrap());
} else {
console.error(result.unwrap_err());
}
`
`typescript
function fetchUserData(userId: string) {
const { Ok, Err } = ResultBuilder<{ name: string; age: number }, string>();
if (userId === "123") {
return Ok({ name: "John Doe", age: 30 });
} else {
return Err("User not found");
}
}
const userResult = fetchUserData("123");
if (userResult.is_ok()) {
console.log("User Data:", userResult.unwrap());
} else {
console.error("Error:", userResult.unwrap_err());
}
`
`typescript
function processFile(filePath: string) {
const { Ok, Err } = ResultBuilder
if (!filePath.endsWith(".txt")) {
return Err("Only .txt files are supported");
}
try {
const fileContent = "File content"; // Simulate reading a file
return Ok(fileContent);
} catch (error) {
return Err("Failed to process the file");
}
}
const fileResult = processFile("example.txt");
if (fileResult.is_ok()) {
console.log("File Content:", fileResult.unwrap());
} else {
console.error("Error:", fileResult.unwrap_err());
}
`
`typescript
async function fetchData(apiUrl: string) {
const { Ok, Err } = ResultBuilder
try {
const response = await fetch(apiUrl);
if (!response.ok) {
return Err(API error: ${response.status});
}
const data = await response.json();
return Ok(data);
} catch (error) {
return Err("Network error");
}
}
(async () => {
const apiResult = await fetchData("https://api.example.com/data");
if (apiResult.is_ok()) {
console.log("API Data:", apiResult.unwrap());
} else {
console.error("Error:", apiResult.unwrap_err());
}
})();
`
The Result class provides a way to handle success and error outcomes in a structured way. Below is an example demonstrating how to use Ok, Err, and the ResultBuilder to handle different results.
`typescript
import { ResultBuilder } from 'result-library';
// deconstruct ResultBuilder and create Ok, Err builder instance
const { Ok, Err } = ResultBuilder
// Simulate a function that can either succeed or fail
function fetchData(success: boolean) {
if (success) {
return Ok('Data retrieved successfully');
} else {
return Err('Failed to retrieve data');
}
}
// Simulate a success scenario
const successResult = fetchData(true);
if (successResult.is_ok()) {
console.log(successResult.ok()); // Output: 'Data retrieved successfully'
} else {
console.log(successResult.err());
}
// Simulate an error scenario
const errorResult = fetchData(false);
if (errorResult.is_err()) {
console.log(errorResult.err()); // Output: 'Failed to retrieve data'
} else {
console.log(errorResult.ok());
}
try {
console.log(successResult.unwrap()); // Output: 'Data retrieved successfully'
console.log(errorResult.unwrap()); // Throws error: "Called unwrap() on an Ok value"
} catch (e) {
console.error(e.message);
}
try {
console.log(successResult.unwrap_err()); // Throws error: "Called unwrap_err() on an Ok value"
} catch (e) {
console.error(e.message);
}
`
These helpers make control flow expressive while remaining type-safe.
`typescript
import { Ok, Err, type Result } from 'result-library';
// andThen: chain computations if Ok, otherwise propagate Err
const doubleIfOk: Result
.andThen((n) => new Ok
// orElse: recover from Err, pass through Ok unchanged
const recoverFromErr: Result
.orElse((e) => new Err
// expect / expectErr: unwrap with custom error messages
new Ok
// throws: Error('must be an error')
new Ok
// tap / tapErr: side-effects without changing the Result
let seenOk: number | undefined;
let seenErr: string | undefined;
new Ok
new Err
`
1. Eliminates Ambiguity: Clear distinction between success and error states.
2. Improves Readability: Code is more declarative and self-documenting.
3. Avoids Exceptions: Encourages error handling through return types instead of exceptions.
4. Enhances Debugging: Easily identify and manage error cases.
A generic class representing either a success (Ok) or failure (Err) value.
#### Methods:
- is_ok(): boolean: Returns true if the result is Ok.is_err(): boolean
- : Returns true if the result is Err.ok(): A
- : Retrieves the success value.err(): E
- : Retrieves the error value.unwrap(): A
- : Returns the success value or throws an error if the result is Err.unwrap_err(): E
- : Returns the error value or throws an error if the result is Ok.unwrapErr(): E
- : CamelCase alias for unwrap_err().when
- : Branch on Ok/Err and return R.fold
- : Async-friendly branching; handlers may return R or Promise.map
-
A subclass of Result representing a success state.
A subclass of Result representing an error state.
An interface for creating Ok and Err instances.
- Ok(value: A): Ok: Creates an Ok result with the given value.Err
- : Creates an Err result with the given error.
Contributions are welcome! Please open an issue or submit a pull request for enhancements or bug fixes.
This library is licensed under the MIT License. See LICENSE` for details.