Técnicas avanzadas de manejo de errores en TypeScript

El manejo eficaz de errores es crucial para crear aplicaciones TypeScript robustas. Más allá de los bloques try-catch básicos, TypeScript ofrece varias técnicas avanzadas para manejar errores de manera elegante y garantizar la confiabilidad del código. Este artículo explora algunas de estas estrategias avanzadas de manejo de errores.

1. Clases de error personalizadas

La creación de clases de error personalizadas le permite representar distintos tipos de errores con mayor precisión. Los errores personalizados pueden incluir propiedades o métodos adicionales que pueden ayudar a identificar y manejar problemas específicos.

class CustomError extends Error {
  constructor(public message: string, public code: number) {
    super(message);
    this.name = 'CustomError';
  }
}

function throwError() {
  throw new CustomError('Something went wrong', 500);
}

try {
  throwError();
} catch (error) {
  if (error instanceof CustomError) {
    console.error(`Error: ${error.message}, Code: ${error.code}`);
  } else {
    console.error('Unexpected error:', error);
  }
}

En este ejemplo, CustomError extiende la clase incorporada Error y agrega una propiedad code para especificar un código de error.

2. Manejo de errores en código asincrónico

El código asincrónico suele requerir un manejo especial de los errores. El uso de async y await junto con los bloques try-catch puede simplificar el manejo de errores en operaciones asincrónicas.

async function fetchData(url: string): Promise {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new CustomError('Failed to fetch data', response.status);
    }
    const data = await response.json();
    console.log(data);
  } catch (error) {
    if (error instanceof CustomError) {
      console.error(`Error: ${error.message}, Code: ${error.code}`);
    } else {
      console.error('Unexpected error:', error);
    }
  }
}

fetchData('https://api.example.com/data');

Este ejemplo demuestra cómo manejar errores de una llamada asincrónica fetch utilizando async, await y try-catch.

3. Límites de error en React con TypeScript

Al trabajar con React y TypeScript, los límites de error ayudan a detectar errores en el árbol de componentes y muestran una interfaz de usuario alternativa. La implementación de límites de error con TypeScript garantiza la seguridad de tipos y el manejo adecuado de errores.

import React, { Component, ErrorInfo } from 'react';

interface Props {}

interface State {
  hasError: boolean;
}

class ErrorBoundary extends Component<Props, State> {
  constructor(props: Props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(): State {
    return { hasError: true };
  }

  componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
    console.error('Error caught by boundary:', error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>
    }

    return this.props.children;
  }
}

export default ErrorBoundary;

En este ejemplo de React, el componente ErrorBoundary detecta errores en sus componentes secundarios y muestra una interfaz de usuario alternativa si ocurre un error.

4. Uso de protectores de tipos para tipos de error

Las protecciones de tipo ayudan a delimitar el tipo de un error en TypeScript. Esto resulta especialmente útil cuando se manejan errores con distintos tipos o de varias fuentes.

function isCustomError(error: any): error is CustomError {
  return error instanceof CustomError;
}

try {
  throw new CustomError('Example error', 400);
} catch (error) {
  if (isCustomError(error)) {
    console.error(`CustomError: ${error.message}, Code: ${error.code}`);
  } else {
    console.error('Unknown error:', error);
  }
}

La función isCustomError es una protección de tipo que ayuda a determinar si el error detectado es una instancia de CustomError.

5. Manejo centralizado de errores

En el caso de aplicaciones de gran tamaño, la centralización del manejo de errores puede simplificar la gestión de errores y garantizar la coherencia. Esto se puede hacer mediante middleware en Express.js o controladores de errores globales en otros marcos.

import express, { Request, Response, NextFunction } from 'express';

const app = express();

app.use((err: any, req: Request, res: Response, next: NextFunction) => {
  console.error('Centralized Error:', err.message);
  res.status(500).send('Internal Server Error');
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Este ejemplo muestra un controlador de errores centralizado para una aplicación Express.js. Detecta todos los errores y responde con un mensaje genérico.

Conclusión

Las técnicas avanzadas de manejo de errores en TypeScript mejoran la solidez de sus aplicaciones al brindar más control sobre la gestión de errores. Las clases de error personalizadas, el manejo de errores asincrónicos, el uso de límites de error en React, las protecciones de tipo y el manejo centralizado de errores son estrategias esenciales para una gestión de errores eficaz. La implementación de estas técnicas dará como resultado un código más fácil de mantener y confiable.