Error Handling in TypeScript

Jun 24, 2025

I’m not very familiar with TypeScript patterns for handling errors. I was wondering what would be an interesting way to define domain-specific error types so that I can be very specific on what happened inside a function execution.

Consider a createUser function that creates a user. We can create a generic Rust-like Result type:

type Result<T, E> = 
  | { success: true; value: T }
  | { success: false; error: E };

Then define domain-specific error types as a discriminated union:

type CreateUserError =
  | { type: 'EmailAlreadyExists'; email: string }
  | { type: 'InvalidEmailFormat'; email: string }
  | { type: 'WeakPassword'; reason: string };

Our createUser function becomes:

function createUser(email: string, password: string): Result<User, CreateUserError> {
  if (!isValidEmail(email)) {
    return { success: false, error: { type: 'InvalidEmailFormat', email } };
  }

  if (!isStrongPassword(password)) {
    return { success: false, error: { type: 'WeakPassword', reason: 'Too short' } };
  }

  if (emailExists(email)) {
    return { success: false, error: { type: 'EmailAlreadyExists', email } };
  }

  const user = new User(email, password);
  return { success: true, value: user };
}

#typescript #error-handling