Last active
June 24, 2025 15:41
-
-
Save fredericoo/985cec41ddfbe62b4b65d8e14a581b33 to your computer and use it in GitHub Desktop.
result
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export class UnhandledError extends Error { | |
originalError: unknown; | |
constructor(originalError: unknown) { | |
super('Unhandled error'); | |
this.originalError = originalError; | |
this.name = 'UnhandledError'; | |
} | |
} | |
type AttemptSuccess<T> = readonly [null, T]; | |
type AttemptFailure<E> = readonly [E, null]; | |
type AttemptResult<E, T> = AttemptSuccess<T> | AttemptFailure<E>; | |
export type AttemptResultAsync<E, T> = Promise<AttemptResult<E, Awaited<T>>>; | |
export const result = { | |
fn: <const E, const R>(fn: (...args: any) => AttemptResult<E, R>): AttemptResult<E | UnhandledError, R> => { | |
try { | |
return fn(); | |
} catch (error) { | |
return result.err(new UnhandledError(error)); | |
} | |
}, | |
fnAsync: async <const E, const R>( | |
fn: (...args: any) => AttemptResultAsync<E, R>, | |
): AttemptResultAsync<E | UnhandledError, R> => { | |
try { | |
return await fn(); | |
} catch (error) { | |
return Promise.resolve(result.err(new UnhandledError(error))); | |
} | |
}, | |
ok: <const R>(success: R): AttemptSuccess<R> => [null, success], | |
err: <const E>(error: E): AttemptFailure<E> => [error, null], | |
}; | |
/** Examples */ | |
const [error, data] = result.fn((a: number, b: number) => { | |
if (b === 0) return result.err('Cannot divide by zero'); | |
return result.ok(a / b); | |
}); | |
if (error) { | |
console.log('you got', error); | |
// ^? "Cannot divide by zero" | UnhandledError | |
if (error instanceof UnhandledError) { | |
console.log('something really unexpected happened'); | |
} else { | |
console.log('couldnt divide because', error); | |
// ^? "Cannot divide by zero" | |
} | |
} else { | |
console.log('you got', data); | |
// ^? number | |
} | |
const [error2, data2] = await result.fnAsync(async (a: number, b: number) => { | |
if (b === 0) return result.err('Cannot divide by zero'); | |
return result.ok(a / b); | |
}); | |
if (error2) { | |
console.log('you got', error2); | |
// ^? "Cannot divide by zero" | UnhandledError | |
} else { | |
console.log('you got', data2); | |
// ^? number | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment