Skip to content

Instantly share code, notes, and snippets.

@christophemarois
Last active April 15, 2025 13:55
Show Gist options
  • Save christophemarois/b22b71b0aafe4814228cfaa4cc2e53f3 to your computer and use it in GitHub Desktop.
Save christophemarois/b22b71b0aafe4814228cfaa4cc2e53f3 to your computer and use it in GitHub Desktop.
attempt.ts
/** Make sure that an unknown object is an error. If it's not, wrap it in an
* error with a useful inspection message */
export function ensureError(err: unknown): Error {
if (err instanceof Error) {
return err
}
let data: string
try {
data = JSON.stringify(err)
if (data.length > 256) {
data = data.slice(0, 255) + '…'
}
} catch (err) {
data = `(failed to JSON.stringify: "${err}") `
}
return new Error(`Non-error object was thrown or rejected: ${data}`, {
cause: err,
})
}
/** Result discriminated union */
type Result<Ok, Err> = [Ok, null] | [null, Err]
/** Runs a sync/async function and wraps its result/error in a {@link Result}
* discriminated union. To be removed when
* https://github.com/arthurfiorette/proposal-try-operator is available */
export function attempt<Ok, Err extends Error = Error>(fn: () => Ok) {
type AttemptReturnType<Ok, Err> = Ok extends Promise<infer ResolvedOk>
? Promise<Result<ResolvedOk, Err>>
: Result<Ok, Err>
try {
const result = fn()
if (result instanceof Promise) {
return result
.then((resolved) => [resolved, null])
.catch((e) => {
return [null, ensureError(e)]
}) as AttemptReturnType<Ok, Err>
} else {
return [result, null] as AttemptReturnType<Ok, Err>
}
} catch (e) {
return [null, ensureError(e)] as AttemptReturnType<Ok, Err>
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment