Error handling is a crucial aspect of any programming language, and TypeScript is no exception. In this section, we will explore how to handle errors effectively in TypeScript, ensuring that your applications are robust and reliable.

Key Concepts

  1. Error Types: Understanding the different types of errors (syntax errors, runtime errors, logical errors).
  2. Try-Catch-Finally: Using try-catch-finally blocks to handle exceptions.
  3. Custom Error Classes: Creating custom error classes for more specific error handling.
  4. Error Handling in Promises: Managing errors in asynchronous code using Promises.
  5. Error Handling with Async/Await: Handling errors in asynchronous functions using async/await.

Error Types

Syntax Errors

Syntax errors occur when the code does not follow the syntax rules of the language. These are usually caught by the TypeScript compiler.

// Syntax Error Example
let a = 10
console.log(a) // Missing semicolon

Runtime Errors

Runtime errors occur during the execution of the program. These are typically handled using try-catch blocks.

// Runtime Error Example
let b: number = 10;
console.log(b.toUpperCase()); // Error: b.toUpperCase is not a function

Logical Errors

Logical errors are mistakes in the logic of the program. These are the hardest to detect and fix.

// Logical Error Example
function calculateArea(radius: number): number {
    return 2 * Math.PI * radius; // Incorrect formula for area
}

Try-Catch-Finally

The try-catch-finally block is used to handle exceptions that occur during the execution of a block of code.

try {
    // Code that may throw an error
    let result = riskyOperation();
    console.log(result);
} catch (error) {
    // Code to handle the error
    console.error("An error occurred:", error);
} finally {
    // Code that will always execute
    console.log("Operation completed.");
}

Explanation

  • try: Contains the code that may throw an error.
  • catch: Contains the code to handle the error.
  • finally: Contains the code that will always execute, regardless of whether an error occurred or not.

Custom Error Classes

Creating custom error classes allows you to handle specific types of errors more effectively.

class CustomError extends Error {
    constructor(message: string) {
        super(message);
        this.name = "CustomError";
    }
}

try {
    throw new CustomError("This is a custom error");
} catch (error) {
    if (error instanceof CustomError) {
        console.error("Caught a custom error:", error.message);
    } else {
        console.error("An unknown error occurred:", error);
    }
}

Error Handling in Promises

When working with Promises, errors can be handled using the .catch method.

let promise = new Promise((resolve, reject) => {
    // Simulate an error
    reject("Something went wrong");
});

promise
    .then(result => {
        console.log(result);
    })
    .catch(error => {
        console.error("Caught an error:", error);
    });

Error Handling with Async/Await

When using async/await, errors can be handled using try-catch blocks.

async function fetchData() {
    try {
        let response = await fetch("https://api.example.com/data");
        let data = await response.json();
        console.log(data);
    } catch (error) {
        console.error("Error fetching data:", error);
    }
}

fetchData();

Practical Exercises

Exercise 1: Basic Try-Catch

Write a function that attempts to parse a JSON string and handles any errors that occur.

function parseJson(jsonString: string) {
    try {
        let result = JSON.parse(jsonString);
        console.log("Parsed JSON:", result);
    } catch (error) {
        console.error("Failed to parse JSON:", error);
    }
}

// Test the function
parseJson('{"name": "John"}'); // Should log the parsed JSON
parseJson('Invalid JSON'); // Should log an error

Exercise 2: Custom Error Class

Create a custom error class for handling validation errors and use it in a function that validates user input.

class ValidationError extends Error {
    constructor(message: string) {
        super(message);
        this.name = "ValidationError";
    }
}

function validateUserInput(input: string) {
    if (input.trim() === "") {
        throw new ValidationError("Input cannot be empty");
    }
    console.log("Valid input:", input);
}

// Test the function
try {
    validateUserInput("John Doe"); // Should log the valid input
    validateUserInput(""); // Should throw a ValidationError
} catch (error) {
    if (error instanceof ValidationError) {
        console.error("Validation error:", error.message);
    } else {
        console.error("An unknown error occurred:", error);
    }
}

Summary

In this section, we covered the basics of error handling in TypeScript, including:

  • Different types of errors (syntax, runtime, logical).
  • Using try-catch-finally blocks to handle exceptions.
  • Creating custom error classes for specific error handling.
  • Managing errors in Promises and async/await.

Understanding and implementing effective error handling strategies is essential for building robust and reliable applications. In the next section, we will delve into advanced asynchronous patterns to further enhance your TypeScript skills.

© Copyright 2024. All rights reserved