Skip to content

Instantly share code, notes, and snippets.

@peplocanto
Created June 29, 2023 13:42
Show Gist options
  • Save peplocanto/b53559e4b3978ac55fec98ab42ae3e1d to your computer and use it in GitHub Desktop.
Save peplocanto/b53559e4b3978ac55fec98ab42ae3e1d to your computer and use it in GitHub Desktop.
no-try npm package typing

Enhanced Error Handling in TypeScript

In this guide, we'll present a handy TypeScript utility that can streamline your error handling process. This utility provides a simple and clear way to encapsulate potential errors and handle them gracefully.

Snippets are based on no-try npm package (link below).

TypeScript Snippet: useTry and useTryAsync

The TypeScript utility is composed of two main functions, useTry and useTryAsync.

These two functions execute a given function and handle any potential errors that may be thrown. If an error occurs, it is caught and returned along with null for the data. Conversely, if no error is thrown, the function's return data is returned along with null for the error.

The type NoTryResult<T, E> represents the potential outcomes of this operation. The result will be either an error with no data ([E, null]), or data with no error ([null, T]).

Here is the TypeScript code snippet:

export type NoTryResult<T, E = Error> = [E, null] | [null, T];

function noop(): null {
  return null;
}

export function useTry<T, E = Error>(
  fn: () => T,
  handleErr: (error: E) => void = noop
): NoTryResult<T, E> {
  try {
    return [null, fn()];
  } catch (err) {
    handleErr(err as E);
    return [err as E, null];
  }
}

export async function useTryAsync<T, E = Error>(
  fn: () => Promise<T>,
  handleErr: (error: E) => void = noop
): Promise<NoTryResult<T, E>> {
  try {
    return [null, await fn()];
  } catch (err) {
    handleErr(err as E);
    return [err as E, null];
  }
}

Example of Use

Below is an example of how you could use these utilities:

const [error, data] = await useTryAsync(
  () => fetchData(),
  (e) => console.log(e) // Can be omitted
);
if (error) return;
handleUserData(data); // TypeScript understands `data` is not null

In the code snippet above, useTryAsync tries to execute fetchData. If fetchData throws an error, the error is handled and returned. If fetchData succeeds, the data is returned. The handleUserData function is then safely called with the data.

JavaScript Version

Here is a version of the utility in vanilla JavaScript:

function noop() {
  return null;
}

function useTry(fn, handleErr = noop) {
  try {
    return [null, fn()];
  } catch (err) {
    handleErr(err);
    return [err, null];
  }
}

async function useTryAsync(fn, handleErr = noop) {
  try {
    return [null, await fn()];
  } catch (err) {
    handleErr(err);
    return [err, null];
  }
}

Please note that due to the lack of TypeScript's static typing, the JavaScript version doesn't provide the same level of type safety as the TypeScript version.

References

no-try npm

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