TryAsync

Just a proof of concept for a try..catch inspired from the Safe Assignment Operator proposal.

export function Try<T extends (...args: any[]) => any>(
  fn: T,
  ...args: Parameters<T>
): [Error | null, ReturnType<T> | null] {
  try {
    const result = fn(...args);
    return [null, result];
  } catch (error) {
    return [error instanceof Error ? error : new Error(String(error)), null];
  }
}

async function TryAsync<T extends (...args: any[]) => Promise<any>>(
  fn: T,
  ...args: Parameters<T>
): Promise<[Error | null, Awaited<ReturnType<T>> | null]> {
  try {
    const result = await fn(...args);
    return [null, result];
  } catch (error) {
    return [error instanceof Error ? error : new Error(String(error)), null];
  }
}

Example usage:

function divide(a: number, b: number) {
  return a / b;
}

const [error, result] = Try(divide, 10, 0);
if (error) {
  console.error(`Error performing division: ${error}`);
}

function getPostTitles(filter: string): string[] {
  return fetch(`https://example.com/api/posts?category=${filter}`);
}

const [error, result] = TryAsync(getPostTitles, "blog");
if (error) {
  console.error("Unable to retrieve posts.");
}

As a proof of concept this functions aren't for production code. They also lacks of DX because of their signature, which requires to pass the callable function separated from its parameters.

A valid alternative I found is the library TypeGuard from Jordan Hall which provides better try-catch functions and more intersting patterns. It's downloadable for Deno at jsr:@jordanhall/typeguard.