Search
⌘K

Try Catch Async

Utility for handling async functions, and forcing you to handle error cases.

Example Usage

import { tryCatchAsync } from './try-catch-async';

// NOTE: 
// - "tryCatchAsync" requires an async function to be passed as argument "cb"
// - "tryCatchAsync" never throws
// - in case "cb" throws, "tryCatchAsync" returns a discriminated union with "status === 'error'" and "error"
// - in case "cb" doesn't throw, "tryCatchAsync" returns a discriminated union with "status === 'success'" and "data" 

const result = await tryCatchAsync(async () => {
  return {
    message: 'hello',
  };
})

// you must check the discriminated union on "status"
if (result.status === 'error') {
  console.log(result.error);
  return;
}

// so here we know that "status" === 'success' and "data" is defined
const data = result.data;
// data
{
  message: string
}

Dependencies

No dependencies

Auto Install

npx shadcn@latest add https://shadcn-registry-ts.vercel.app/r/util-try-catch-async.json

Manual Install

try-catch-async.ts
/**
 * Source: http://localhost:3000
 */

type ResultError = {
  status: 'error';
  error: unknown;
};
type ResultSuccess<T> = {
  status: 'success';
  data: T;
};

type Result<T> = ResultError | ResultSuccess<T>;

export const tryCatchAsync = async <T>(fn: () => Promise<T>): Promise<Result<T>> => {
  try {
    const data = await fn();
    return { status: 'success', data } as const;
  } catch (error) {
    return { status: 'error', error } as const;
  }
};

Test

try-catch-async.test.ts
import { describe, it, expect } from 'vitest';
import { repeatAsyncFnInParallel } from '../utility-framework/vitest.utils';
// import { calculateFrequenciesStats } from './math';

import { tryCatchAsync } from './try-catch-async';


describe('tryCatchAsync', () => {

  it('do it', async () => {

    const FREQUENCIES = {
      success: 0,
      error: 0
    };

    await repeatAsyncFnInParallel(1_000, async () => {

      const result = await tryCatchAsync(async () => {
        const isSuccess = Math.random() > 0.5;
        if (isSuccess) return { ok: true };
        throw new Error('Fake error');
      });

      expect(result).toBeTypeOf('object');
      expect(result).toHaveProperty('status');
      expect(result.status).oneOf(['success', 'error']);

      if (result.status === 'success') {
        expect(result.data).toBeTypeOf('object');
        expect(result.data).toHaveProperty('ok');
        expect(result.data.ok).toBe(true);

        FREQUENCIES.success++;
      }

      if (result.status === 'error') {
        expect(result.error).toBeInstanceOf(Error);

        FREQUENCIES.error++;
      }
    });

    // check frequencies
    // console.log(calculateFrequenciesStats(FREQUENCIES));
    expect(FREQUENCIES.success).toBeGreaterThan(0);
    expect(FREQUENCIES.error).toBeGreaterThan(0);

  });

});

Command Palette

Search for a command to run...