Async/await wrapper for easy error handling that converts Promise rejections into manageable error/data tuples
npx @tessl/cli install tessl/npm-await-to-js@3.0.0await-to-js is a lightweight TypeScript utility library that provides an elegant wrapper for handling errors in async/await functions. It eliminates the need for try-catch blocks by converting Promise rejections into manageable error/data tuples, making error handling more explicit and reducing code complexity.
npm install await-to-jsimport to from "await-to-js";Named import:
import { to } from "await-to-js";For CommonJS:
const to = require("await-to-js").default;import to from "await-to-js";
async function fetchUserData(userId: number) {
// Instead of try-catch blocks
const [err, user] = await to(UserModel.findById(userId));
if (err) {
console.error("Failed to fetch user:", err);
return null;
}
return user;
}
// With TypeScript generics for type safety
interface User {
id: number;
name: string;
email: string;
}
const [err, user] = await to<User>(fetchUser(123));
if (!err && user) {
console.log(user.name); // TypeScript knows user is of type User
}Converts Promise rejections into manageable error/data tuples, eliminating the need for try-catch blocks in async/await code.
/**
* Async/await wrapper for easy error handling
* @param promise - The promise to wrap
* @param errorExt - Additional information to extend the error object
* @returns Promise that resolves to [error, undefined] on rejection or [null, data] on success
*/
function to<T, U = Error>(
promise: Promise<T>,
errorExt?: object
): Promise<[U, undefined] | [null, T]>;Parameters:
promise: Promise<T> - The promise to wrap and handleerrorExt?: object - Optional additional information to merge into the error objectReturns:
Promise<[U, undefined] | [null, T]> - A promise that resolves to:
[error, undefined] when the original promise is rejected[null, data] when the original promise is resolvedGeneric Type Parameters:
T - The type of the resolved value from the original promiseU - The type of the error (defaults to Error)Usage Examples:
import to from "await-to-js";
// Basic usage
const [err, result] = await to(fetch("/api/data"));
if (err) {
console.error("Request failed:", err);
} else {
console.log("Success:", result);
}
// With TypeScript generics
interface ApiResponse {
data: string[];
status: number;
}
const [err, response] = await to<ApiResponse>(apiCall());
if (!err) {
response.data.forEach(item => console.log(item)); // Type-safe access
}
// With error extension
const [err, user] = await to(
UserService.findById(123),
{ context: "user-lookup", requestId: "req-456" }
);
if (err) {
console.error("Enhanced error:", err);
// err now contains: { ...originalError, context: "user-lookup", requestId: "req-456" }
}
// Complex workflow without try-catch
async function createUserTask(userId: number, taskName: string) {
let err, user, task, notification;
[err, user] = await to(UserModel.findById(userId));
if (!user) return { error: "User not found" };
[err, task] = await to(TaskModel.create({ userId: user.id, name: taskName }));
if (err) return { error: "Failed to create task" };
if (user.notificationsEnabled) {
[err, notification] = await to(NotificationService.send(user.id, "Task created"));
if (err) console.warn("Notification failed:", err);
}
return { success: true, task };
}/**
* Return type for the to function - discriminated union representing either success or failure
*/
type ToResult<T, U = Error> = [U, undefined] | [null, T];The to function transforms standard Promise behavior:
[null, data] where data is the resolved value[error, undefined] where error is the rejection reasonerrorExt is provided, it merges additional properties into the error objectTraditional vs await-to-js comparison:
// Traditional approach
try {
const user = await UserModel.findById(123);
const task = await TaskModel.create({ userId: user.id, name: "Demo" });
return task;
} catch (error) {
console.error("Operation failed:", error);
return null;
}
// await-to-js approach
const [userErr, user] = await to(UserModel.findById(123));
if (userErr) {
console.error("User lookup failed:", userErr);
return null;
}
const [taskErr, task] = await to(TaskModel.create({ userId: user.id, name: "Demo" }));
if (taskErr) {
console.error("Task creation failed:", taskErr);
return null;
}
return task;