Tecniche avanzate di gestione degli errori in TypeScript

Una gestione efficace degli errori è fondamentale per la creazione di applicazioni TypeScript robuste. Oltre ai blocchi try-catch di base, TypeScript fornisce diverse tecniche avanzate per gestire gli errori con eleganza e garantire l'affidabilità del codice. Questo articolo esplora alcune di queste strategie avanzate di gestione degli errori.

1. Classi di errore personalizzate

La creazione di classi di errore personalizzate consente di rappresentare diversi tipi di errori in modo più accurato. Gli errori personalizzati possono includere proprietà o metodi aggiuntivi, che possono aiutare a identificare e gestire problemi specifici.

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);
  }
}

In questo esempio, CustomError estende la classe integrata Error e aggiunge una proprietà code per specificare un codice di errore.

2. Gestione degli errori nel codice asincrono

Il codice asincrono spesso richiede una gestione speciale per gli errori. L'utilizzo di async e await insieme ai blocchi try-catch può semplificare la gestione degli errori nelle operazioni asincrone.

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');

Questo esempio illustra la gestione degli errori derivanti da una chiamata asincrona fetch utilizzando async, await e try-catch.

3. Limiti di errore in React con TypeScript

Quando si lavora con React e TypeScript, i limiti di errore aiutano a catturare gli errori nell'albero dei componenti e a visualizzare un'interfaccia utente di fallback. L'implementazione dei limiti di errore con TypeScript garantisce la sicurezza dei tipi e una corretta gestione degli errori.

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;

In questo esempio React, il componente ErrorBoundary rileva gli errori nei suoi componenti figlio e visualizza un'interfaccia utente di fallback se si verifica un errore.

4. Utilizzo di Type Guard per i tipi di errore

Le protezioni di tipo aiutano a restringere il tipo di errore in TypeScript. Ciò è particolarmente utile quando si gestiscono errori con tipi diversi o provenienti da varie fonti.

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 funzione isCustomError è una protezione di tipo che aiuta a determinare se l'errore rilevato è un'istanza di CustomError.

5. Gestione centralizzata degli errori

Per applicazioni di grandi dimensioni, la centralizzazione della gestione degli errori può semplificare la gestione degli errori e garantire la coerenza. Ciò può essere fatto utilizzando middleware in Express.js o gestori di errori globali in altri framework.

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');
});

Questo esempio illustra un gestore di errori centralizzato per un'applicazione Express.js. Cattura tutti gli errori e risponde con un messaggio generico.

Conclusione

Le tecniche avanzate di gestione degli errori in TypeScript migliorano la robustezza delle tue applicazioni offrendo un maggiore controllo sulla gestione degli errori. Classi di errore personalizzate, gestione degli errori asincroni, utilizzo di limiti di errore in React, protezioni di tipo e gestione centralizzata degli errori sono strategie essenziali per una gestione efficace degli errori. L'implementazione di queste tecniche porterà a un codice più manutenibile e affidabile.