Understanding Generics in TypeScript

Aug 22, 2024

Notes on Generics in TypeScript

Introduction to Generics

  • Generics can be intimidating due to the syntax (angle brackets, variables like T, K, V).
  • Goal of the video: Simplify understanding of generics in TypeScript.
  • Encourage viewers to check out a full course on TypeScript.

Understanding Generics Through Examples

Function Example: Getting First Element of an Array

  • Initial Function: Accepts an array of number:
    function getFirstElement(arr: number[]): number {
        return arr[0];
    }
    
  • Problem: Cannot accept strings without generating errors.
    • Result: If typed as any[], return type is any, which is not useful.

Implementing Generics

  • Purpose of Generics: Allow a function to handle different types while maintaining type safety.
  • Generic Function:
    • Syntax: Place angle brackets after the function name to define a generic type.
    • Example:
    function getFirstElement<T>(arr: T[]): T {
        return arr[0];
    }
    
  • Benefits:
    • TypeScript infers type based on the passed array:
      • For a number array, returns type number.
      • For a string array, returns type string.

Type Inference in Generics

  • TypeScript infers types for generics most of the time.
  • Example of usage: document.querySelector and Array.prototype.map().

Generics with Collections

  • Maps and Sets:
    • Collections can have generic types as well:
    const myMap = new Map<string, number>();
    
  • Nested Generics: Can nest generics as needed.
    • Example:
    const nestedMap = new Map<string, Map<string, number>>();
    

Generic Types

Defining Generic Types

  • Example: Creating a generic type for API responses:
    type ApiResponse<T> = {
        data: T;
        isError: boolean;
    };
    
  • Using Generics for Specific Responses: Create specific response types:
    • Example: User response:
    type UserResponse = ApiResponse<{ name: string; age: number }>;  
    

Default Values for Generics

  • Set default types in generics:
    type ApiResponse<T = { status: number }> = {...};
    
  • Allows flexibility while maintaining a default structure.

Constraints on Generics

  • Limit generic types to specific structures:
    type ApiResponse<T extends object> = {...};
    
  • Example: Must always be an object type.

Conclusion

  • Key Takeaway: Use generics when you want a function or type to handle multiple types while maintaining type uniformity.
  • Majority of use cases involve simple generics; more complex features are less common.

Additional Resources

  • Mention of simplified TypeScript course in the video for deeper understanding.