Package Exports
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (go-errors) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
go-errors
A TypeScript library that brings Go-style error handling to JavaScript/TypeScript. Handle errors elegantly without try-catch blocks, using a functional approach that's both type-safe and intuitive.
Features
- 🎯 Type-safe error handling with full TypeScript support
- 🔄 Go-style result tuples
[value, error]
- ⚡ Zero dependencies and lightweight
- 🔀 Unified API for both synchronous and asynchronous operations
- 🛡️ Predictable error handling without try-catch blocks
- 📦 Tree-shakeable and optimized for bundle size
Installation
npm install go-errors
# or
yarn add go-errors
# or
pnpm add go-errors
Quick Start
import { go } from 'go-errors';
// Synchronous usage
const [value, error] = go(() => {
// Your code that might throw
return "success";
});
if (error) {
console.error("Something went wrong:", error.message);
} else {
console.log("Got value:", value);
}
// Asynchronous usage
const [data, err] = await go(fetch("https://api.example.com/data"));
if (err) {
console.error("API call failed:", err.message);
} else {
console.log("API data:", data);
}
Usage Examples
Basic Error Handling
import { go } from 'go-errors';
function divide(a: number, b: number): number {
if (b === 0) throw new Error("Division by zero");
return a / b;
}
// Synchronous error handling
const [result, err] = go(() => divide(10, 0));
if (err) {
console.log("Failed to divide:", err.message); // "Failed to divide: Division by zero"
} else {
console.log("Result:", result);
}
Async/Promise Handling
import { go } from 'go-errors';
async function fetchUserData(id: string) {
const [response, fetchError] = await go(
fetch(`https://api.example.com/users/${id}`)
);
if (fetchError) {
return [null, fetchError] as const;
}
const [data, parseError] = await go(response.json());
if (parseError) {
return [null, parseError] as const;
}
return [data, null] as const;
}
// Usage
async function main() {
const [userData, error] = await fetchUserData("123");
if (error) {
console.error("Failed to fetch user:", error.message);
return;
}
console.log("User data:", userData);
}
Custom Error Types
import { go } from 'go-errors';
class ValidationError extends Error {
constructor(message: string) {
super(message);
this.name = 'ValidationError';
}
}
function validateUser(user: unknown) {
if (typeof user !== 'object' || !user) {
throw new ValidationError('Invalid user object');
}
return user;
}
const [user, error] = go<unknown, ValidationError>(() =>
validateUser({ name: 'John' })
);
if (error) {
if (error instanceof ValidationError) {
console.log("Validation failed:", error.message);
} else {
console.log("Unknown error:", error.message);
}
}
Working with Multiple Operations
import { go } from 'go-errors';
async function processUserData(userId: string) {
// Fetch user
const [user, userError] = await go(fetchUser(userId));
if (userError) return [null, userError] as const;
// Fetch user's posts
const [posts, postsError] = await go(fetchUserPosts(userId));
if (postsError) return [null, postsError] as const;
// Process everything
return [{
user,
posts,
timestamp: new Date()
}, null] as const;
}
Edge Cases
The library handles various edge cases gracefully:
Circular References: Objects with circular references are handled gracefully with descriptive error messages:
const circular = { foo: 'bar' }; circular.self = circular; const [result, err] = go(() => circular); // err.message will contain information about the circular structure
Special Objects: Special JavaScript objects are properly stringified:
// RegExp const [_, regexErr] = go(() => { throw /test/gi; }); console.log(regexErr.message); // "/test/gi" // Date const [_, dateErr] = go(() => { throw new Date(); }); // Preserves date format in error message
Falsy Values: Properly handles falsy values (undefined, null, 0, false, ''):
const [result, err] = go(() => false); console.log(result === false); // true console.log(err === null); // true
API Reference
Core Functions
go<T, E = Error>(fn: () => T): Result<T, E>
go<T, E = Error>(promise: Promise<T>): Promise<Result<T, E>>
The main function that handles both synchronous and asynchronous operations.
// Sync
const [value, error] = go(() => someOperation());
// Async
const [value, error] = await go(somePromise);
goSync<T, E = Error>(fn: () => T): Result<T, E>
Specifically handles synchronous operations.
const [value, error] = goSync(() => {
// synchronous code that might throw
return someValue;
});
goAsync<T, E = Error>(promise: Promise<T>): Promise<Result<T, E>>
Specifically handles asynchronous operations.
const [value, error] = await goAsync(fetch('https://api.example.com'));
Types
type Result<T, E = Error> = [T, null] | [null, E];
Best Practices
Type Your Errors: Always specify error types for better type safety:
const [value, error] = go<number, ValidationError>(() => validate(input));
Early Returns: Use early returns with error checking:
const [data, error] = await fetchData(); if (error) return [null, error] as const;
Error Propagation: Propagate errors up the call stack:
function processData() { const [data, error] = getData(); if (error) return [null, error] as const; // process data }
Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature
) - Commit your changes (
git commit -m 'Add some AmazingFeature'
) - Push to the branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Acknowledgments
- Inspired by Go's error handling pattern
- Built with TypeScript for type safety
- Designed for modern JavaScript/TypeScript applications
Made with ❤️ for the TypeScript community