Skip to content

Instantly share code, notes, and snippets.

@dmorosinotto
Last active March 8, 2023 15:20
Show Gist options
  • Save dmorosinotto/5d6bae82ead06e6b32ef7df34cce753f to your computer and use it in GitHub Desktop.
Save dmorosinotto/5d6bae82ead06e6b32ef7df34cce753f to your computer and use it in GitHub Desktop.
safeCall function (like RUST) + generic SafeResult<T> with TypeScript
//ORIGINAL CODE BY https://twitter.com/mattpocockuk/status/1633064377518628866?s=20
/**
* First, create a type helper that represents
* the result that we'll get from our safe function
*/
export type SafeResult<T> =
| {
ok: true;
value: T;
}
| {
ok: false;
error: unknown;
};
/**
* Next, make a function that wraps the function
* you pass it with a try/catch, then executes it
*/
export const safeCall =
<TArgs extends any[], TReturn>(
func: (...args: TArgs) => TReturn
) =>
(...args: TArgs): SafeResult<TReturn> => {
try {
return {
value: func(...args),
ok: true,
};
} catch (e) {
return {
error: e,
ok: false,
};
}
};
import { safeCall } from "./safeCall.ts";
/**
* Wrap any function you want to error check with this makeSafe wrapper
*/
const randomlyFail = safeCall((input: number) => {
if (input > 0.5) {
throw new Error("oops");
}
return {
input,
};
});
/**
* Finally, you can call it - and it'll return the error if it fails, or the value if it succeeds
*/
const result = randomlyFail(0.25); // SAFE HANDLE ERROR -> SafeResult<T> -> { ok: false, error }
if (!result.ok) { // NOTE CODE FLOW ANALISYS DISCRIMINATE BOTH CASES
result.error; // unknown
} else {
result.value; // { input: number }
}
const rnd = randomlyFail(Math.random()); // SAFE HANDLE BOTH CASES -> SafeResult<T> -> T infer { input: number }
if (rnd.ok) {
console.dir(rnd.value); // T -> infer { input: number }
} else {
console.error(rnd.error); // unknown
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment