[Typescript] Handle Errors with a Generic Result Type

Consider this Result type:

type Result<TResult, TError> =
  | {
      success: true;
      data: TResult;
    }
  | {
      success: false;
      error: TError;
    };

The Result type has two type parameters for TResult and TError.

It returns a discriminated union, with one branch indicating success and returning data, and the other pointing to failure and returning an error.

Next we have a createRandomNumber function that returns a Result type with a number as the data and an Error as the error:

const createRandomNumber = (): Result<number, Error> => {
  const num = Math.random();

  if (num > 0.5) {
    return {
      success: true,
      data: 123,
    };
  }

  return {
    success: false,
    error: new Error("Something went wrong"),
  };
};

This function generates a random number and based on its value, renders a Result type. If the number exceeds 0.5, it returns a successful result with some data. Otherwise, it returns a failure result with an error.

When we create a result variable by calling createRandomNumber, we can see that it is typed as Result:

const result = createRandomNumber();

// hovering over result shows:
const result: Result<number, Error>

We in turn can conditionally check result.success and obtain the correct type for result.data. For example, if result.success is true, then result.data is typed as a number:

const result = createRandomNumber();

if (result.success) {
  console.log(result.data);

  type test = Expect<Equal<typeof result.data, number>>;
} else {
  console.error(result.error);

  type test = Expect<Equal<typeof result.error, Error>>;
}

This pattern proves very handy for error handling, as it eliminates the need for try-catch blocks. Instead, we can directly check if the result was successful and act accordingly, or deal with the error.

posted @ 2024-09-06 15:03  Zhentiw  阅读(8)  评论(0编辑  收藏  举报