Try Catch Async
Utility for make async functions not throwable.
Example Usage
tryCatchAsync
Tip
For a more robust pattern, check Ts Result and Ts Result Zod
Wrap an async function to make it not-throwable, by wrapping it in a try-catch block.
The resulting function:
- never throws
- returns a discriminated union on status that can be
success | error - if the original function throws, returns
{ status: 'error', error: unknown } - if the original function doesn't throw, returns
{ status: 'success', data: <return type of original fn> }
import { tryCatchAsync } from './try-catch-async';
const result = await tryCatchAsync(
async () => {
const isSuccess = Math.random() > 0.5;
if (!isSuccess) throw new Error('Fake error');
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;
{
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
type ResultError = {
status: 'error';
error: unknown;
};
type ResultSuccess<TData> = {
status: 'success';
data: TData;
};
type Result<TSuccessData> = ResultError | ResultSuccess<TSuccessData>;
/**
* Function that run an asyn cfunction inside a try catch block.
*/
export const tryCatchAsync = async <TReturn>(fn: () => Promise<TReturn>): Promise<Result<TReturn>> => {
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...