Skip to content

Instantly share code, notes, and snippets.

@oukayuka
Last active May 1, 2020 03:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save oukayuka/0a3d5b21887449ac184d4c1bb314f1d0 to your computer and use it in GitHub Desktop.
Save oukayuka/0a3d5b21887449ac184d4c1bb314f1d0 to your computer and use it in GitHub Desktop.
TypeScript higher order function which wraps async fetcher and returns with Result<T,E> like Rust
/* eslint-disable max-classes-per-file, no-useless-constructor, lines-between-class-members */
type Result<T, E extends Error> = Ok<T, E> | Err<T, E>;
export class Ok<T, E extends Error> {
constructor(readonly val: T) {}
isOk = (): this is Ok<T, E> => true;
isErr = (): this is Err<T, E> => false;
}
export class Err<T, E extends Error> {
constructor(readonly err: E) {}
isOk = (): this is Ok<T, E> => false;
isErr = (): this is Err<T, E> => true;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const withResult = <T, A extends any[], E extends Error>(
fn: (...args: A) => Promise<T>,
) => async (...args: A): Promise<Result<T, E>> => {
try {
return new Ok(await fn(...args));
} catch (error) {
return new Err(error as E);
}
};
@oukayuka
Copy link
Author

oukayuka commented Apr 17, 2020

Usage:

// fetchUser: (userId: string) => Promise<User>
const data = await withResult(fetchUser)('oukayuka');

if (data.isErr()) {
  console.error(data.err);
} else {
  const user = data.val;
  console.log(`Hello, ${user.name}!`);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment