@appboypov/turbo-response
v0.1.5
Published
Result type (Success/Fail) for operation outcomes in TypeScript/React
Downloads
217
Maintainers
Readme
turbo-response
A TypeScript library providing a type-safe Result type (Success/Fail) for handling operation outcomes without exceptions.
Installation
npm install @appboypov/turbo-responseFeatures
- Type-safe result handling with discriminated unions
- Zero dependencies
- Full TypeScript support with complete type inference
- Functional programming utilities for chaining and transforming results
- Async support with
andThenAsync,recoverAsync, andtraverse - Batch operations with
sequencefor combining multiple results
Quick Start
import { success, fail, fold, isSuccess, TurboResponse } from '@appboypov/turbo-response';
// Creating responses
const successResult = success({ id: '123', name: 'John' });
const failResult = fail(new Error('Not found'));
// Type guards
if (isSuccess(response)) {
console.log(response.result);
}
// Pattern matching with fold
const message = fold(
response,
(data) => `Found user: ${data.name}`,
(error) => `Error: ${error}`
);API
Creating Responses
success<T>(result: T, title?: string, message?: string): Success<T>
Creates a successful response.
const user = success({ id: '1', name: 'John' });
const withMeta = success(data, 'Created', 'User created successfully');fail<T>(error: unknown, title?: string, message?: string, stackTrace?: string): Fail<T>
Creates a failed response.
const error = fail(new Error('Not found'));
const withMeta = fail(err, 'Not Found', 'User does not exist');Type Guards
isSuccess<T>(r: TurboResponse<T>): r is Success<T>
if (isSuccess(response)) {
console.log(response.result); // TypeScript knows this is Success<T>
}isFail<T>(r: TurboResponse<T>): r is Fail<T>
if (isFail(response)) {
console.log(response.error); // TypeScript knows this is Fail<T>
}Pattern Matching
fold<T, R>(response, onSuccess, onFail): R
Transform a response into a single value.
const message = fold(
response,
(user) => `Hello, ${user.name}`,
(error) => `Error: ${error}`
);when<T, R>(response, handlers): R
Pattern match with full response access.
const result = when(response, {
success: (s) => `Got ${s.result.name} - ${s.message}`,
fail: (f) => `Failed: ${f.title}`,
});maybeWhen<T, R>(response, handlers): R
Pattern match with optional handlers and fallback.
const result = maybeWhen(response, {
success: (s) => s.result.name,
orElse: () => 'Unknown',
});Transformations
mapSuccess<T, R>(r, fn): TurboResponse<R>
Transform the success value.
const nameResponse = mapSuccess(userResponse, (user) => user.name);mapFail<T>(r, fn): TurboResponse<T>
Transform the error value.
const mapped = mapFail(response, (err) => new CustomError(err));Chaining
andThen<T, R>(r, fn): TurboResponse<R>
Chain operations that return TurboResponse (flatMap/bind).
const result = andThen(
getUserById('123'),
(user) => getOrdersByUser(user.id)
);andThenAsync<T, R>(r, fn): Promise<TurboResponse<R>>
Async version of andThen for chaining async operations.
const result = await andThenAsync(
fetchUser('123'),
async (user) => fetchOrders(user.id)
);
// Chain multiple async operations
let result = await fetchUser('123');
result = await andThenAsync(result, async (user) => fetchProfile(user.id));
result = await andThenAsync(result, async (profile) => fetchSettings(profile.id));Error Recovery
recover<T>(r, fn): TurboResponse<T>
Attempt to recover from a failure.
const result = recover(
failedResponse,
(error) => success(defaultValue)
);recoverAsync<T>(r, fn): Promise<TurboResponse<T>>
Async version of recover.
const result = await recoverAsync(
failedResponse,
async (error) => {
const fallback = await fetchFallbackData();
return success(fallback);
}
);Unwrapping
unwrap<T>(r): T
Get the success value or throw the error.
try {
const value = unwrap(response);
} catch (error) {
// Handle error
}unwrapOr<T>(r, defaultValue): T
Get the success value or return a default.
const value = unwrapOr(response, defaultUser);unwrapOrCompute<T>(r, compute): T
Get the success value or compute a default lazily.
const value = unwrapOrCompute(response, () => createDefaultUser());Batch Operations
traverse<T, R>(items, fn): Promise<TurboResponse<R[]>>
Apply an async operation to each item, collecting results. Fails fast on first error.
const userIds = ['1', '2', '3'];
const result = await traverse(userIds, async (id) => {
const user = await fetchUser(id);
return user ? success(user) : fail(new Error(`User ${id} not found`));
});
if (isSuccess(result)) {
console.log('All users:', result.result); // User[]
}sequence<T>(responses): TurboResponse<T[]>
Combine an array of responses into a single response. Fails fast on first error.
const responses = [
success(1),
success(2),
success(3),
];
const combined = sequence(responses);
// Success<number[]> with [1, 2, 3]
const withFailure = sequence([
success(1),
fail(new Error('oops')),
success(3),
]);
// Fail - returns the first failureValidation
ensure<T>(r, predicate, error): TurboResponse<T>
Validate the success value against a predicate.
const validated = ensure(
userResponse,
(user) => user.age >= 18,
new Error('Must be 18 or older')
);Utilities
swap<T>(r): TurboResponse<T>
Swap success and fail states.
getResult<T>(r): T | undefined
Safely get the result value.
getError<T>(r): unknown | undefined
Safely get the error value.
getTitle<T>(r): string | undefined
Get the title metadata.
getMessage<T>(r): string | undefined
Get the message metadata.
License
MIT
