Zaawansowane techniki obsługi błędów w TypeScript

Efektywna obsługa błędów jest kluczowa dla tworzenia solidnych aplikacji TypeScript. Oprócz podstawowych bloków try-catch, TypeScript oferuje kilka zaawansowanych technik, aby obsługiwać błędy w sposób elegancki i zapewnić niezawodność kodu. W tym artykule omówiono niektóre z tych zaawansowanych strategii obsługi błędów.

1. Klasy błędów niestandardowych

Tworzenie niestandardowych klas błędów pozwala na dokładniejsze reprezentowanie różnych typów błędów. Niestandardowe błędy mogą obejmować dodatkowe właściwości lub metody, które mogą pomóc w identyfikowaniu i obsłudze konkretnych problemów.

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

W tym przykładzie CustomError rozszerza wbudowaną klasę Error i dodaje właściwość code umożliwiającą określenie kodu błędu.

2. Obsługa błędów w kodzie asynchronicznym

Kod asynchroniczny często wymaga specjalnej obsługi błędów. Użycie async i await wraz z blokami try-catch może uprościć obsługę błędów w operacjach asynchronicznych.

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

W tym przykładzie pokazano obsługę błędów z asynchronicznego wywołania fetch przy użyciu async, await i try-catch.

3. Granice błędów w React z TypeScript

Podczas pracy z React i TypeScript granice błędów pomagają wychwytywać błędy w drzewie komponentów i wyświetlać zapasowy interfejs użytkownika. Implementacja granic błędów za pomocą TypeScript zapewnia bezpieczeństwo typu i właściwą obsługę błędów.

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;

W tym przykładzie React komponent ErrorBoundary wychwytuje błędy w swoich komponentach podrzędnych i wyświetla zapasowy interfejs użytkownika, jeśli wystąpi błąd.

4. Używanie Type Guards dla typów błędów

Strażnicy typów pomagają zawęzić typ błędu w TypeScript. Jest to szczególnie przydatne podczas obsługi błędów o różnych typach lub z różnych źródeł.

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

Funkcja isCustomError to zabezpieczenie typu pomagające ustalić, czy wychwycony błąd jest wystąpieniem CustomError.

5. Centralne przetwarzanie błędów

W przypadku dużych aplikacji centralizacja obsługi błędów może uprościć zarządzanie błędami i zapewnić spójność. Można to zrobić za pomocą middleware w Express.js lub globalnych programów obsługi błędów w innych frameworkach.

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

Ten przykład pokazuje scentralizowany program obsługi błędów dla aplikacji Express.js. Wyłapuje wszystkie błędy i odpowiada ogólną wiadomością.

Wniosek

Zaawansowane techniki obsługi błędów w TypeScript zwiększają solidność aplikacji, zapewniając większą kontrolę nad zarządzaniem błędami. Niestandardowe klasy błędów, obsługa błędów asynchronicznych, używanie granic błędów w React, strażnicy typów i scentralizowana obsługa błędów to podstawowe strategie efektywnego zarządzania błędami. Wdrożenie tych technik doprowadzi do bardziej łatwego w utrzymaniu i niezawodnego kodu.