Last active
August 15, 2024 13:26
-
-
Save remojansen/f345ea7a266cb24b4b7c4773a329c64f to your computer and use it in GitHub Desktop.
"attempt" TypeScript "try" utility
This file contains 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
class Result<T, E = Error> { | |
constructor( | |
private v: T | undefined, | |
private e: E | undefined | |
) {} | |
onSuccess(cb: (v: T) => void) { | |
if (this.v !== undefined) { | |
cb(this.v as T); | |
} | |
} | |
onError(cb: (e: E) => void) { | |
if (this.e !== undefined) { | |
cb(this.e as E); | |
} | |
} | |
get value() { | |
return [this.v, this.e] as [T | undefined, E | undefined]; | |
} | |
} | |
type AttemptCallback<T> = (() => T) | (() => Promise<T>); | |
type AttemptResult<Cb extends AttemptCallback<any>> = | |
Cb extends () => Promise<infer T> | |
? Promise<Result<T, Error>> | |
: Cb extends () => infer T ? Result<T, Error>: never | |
type t1 = AttemptResult<() => number>; | |
type t2 = AttemptResult<() => Promise<number>>; | |
function isPromise<T>(obj: any): obj is Promise<T> { | |
return obj && typeof obj === 'object' && typeof obj.then === 'function'; | |
} | |
export function attempt<T, TCb extends AttemptCallback<T>>(cb: TCb): AttemptResult<typeof cb> { | |
let result: T| Promise<T> | null = null; | |
try { | |
result = cb(); | |
if (isPromise<T>(result)) { | |
return result.then(v => new Result(v, undefined)).catch(e => new Result(undefined, e)) as AttemptResult<typeof cb>; | |
} else { | |
result | |
return new Result<T, Error>(result, undefined) as AttemptResult<typeof cb>; | |
} | |
} catch(e) { | |
return new Result(undefined, e) as AttemptResult<typeof cb>; | |
} | |
} |
This file contains 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
import { attempt } from "./lib.ts"; | |
// Demo sync task with potential failure | |
function mightFail(): number { | |
const randomValue = Math.random(); | |
const failureThreshold = 0.5; // 50% chance to fail | |
if (randomValue < failureThreshold) { | |
throw new Error("Something went wrong!"); | |
} else { | |
return randomValue; | |
} | |
} | |
// Demo async task with potential failure | |
async function asyncMightFail() { | |
return new Promise<number>((resolve, reject) => { | |
try { | |
const result = mightFail(); | |
resolve(result); | |
} catch(e) { | |
reject(e); | |
} | |
}); | |
} | |
function testSync() { | |
const syncResult = attempt(mightFail); | |
const [result, error] = syncResult.value; | |
console.log(result, error); | |
syncResult.onSuccess(console.log); | |
syncResult.onError(console.error); | |
} | |
async function testAsync() { | |
const asyncResult = await attempt(asyncMightFail); | |
const [result, error] = asyncResult.value; | |
console.log(result, error); | |
asyncResult.onSuccess(console.log); | |
asyncResult.onError(console.error); | |
} | |
testSync(); | |
testAsync(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment