Understanding the terminology around unions is essential for working effectively with TypeScript's type system. Unions allow you to combine multiple types into one, providing flexibility and versatility in defining variables, function parameters, and return types. Here are some key terms related to unions in TypeScript:

  1. Union Type:

    A union type is a type formed by combining two or more individual types using the | (pipe) operator. It represents a value that can be of any of the included types. For example:

    type MyUnion = string | number | boolean;
    

    In this example, MyUnion is a union type that can hold values of type string, number, or boolean.

  2. Discriminated Unions:

    Discriminated unions, also known as tagged unions or algebraic data types, are a pattern used to represent a type that can be one of several options, each identified by a discriminant property (a common property shared across the union). This pattern is commonly used in TypeScript to create type-safe representations of different variants or states. For example:

    interface Circle {
      kind: 'circle';
      radius: number;
    }
    
    interface Square {
      kind: 'square';
      sideLength: number;
    }
    
    type Shape = Circle | Square;
    

    Here, the Shape type is a discriminated union, and the kind property is the discriminant that identifies whether a value is a Circle or a Square.

  3. Type Guards:

    Type guards are techniques used to narrow down the type of a variable when working with unions. They allow you to check if a variable is of a specific type and help TypeScript's type inference system make more accurate inferences. Common type guards include typeof checks, instanceof checks, and custom user-defined type guards.

  4. Exhaustiveness Checking:

    Exhaustiveness checking is a mechanism in TypeScript to ensure that all possible cases of a union type are handled in conditional statements or switch blocks. This prevents accidental omissions that could lead to runtime errors. For discriminated unions, TypeScript automatically performs exhaustiveness checking when you use a switch statement with a discriminant.

Understanding these terms will enable you to work effectively with unions and leverage them to write more robust and type-safe code in TypeScript. Unions are a powerful feature that enhances the expressiveness and safety of your programs, and employing them correctly can lead to more maintainable and predictable codebases.


1] Extracting Members of Discriminated Unions

Extracting members of a discriminated union in TypeScript involves using conditional statements or switch blocks to narrow down the type of a variable based on its discriminant property. Discriminated unions are a powerful pattern in TypeScript that allow you to create type-safe representations of different variants or states.

Here's how you can extract members of a discriminated union:

// Discriminated union representing different shapes
interface Circle {
  kind: 'circle';
  radius: number;
}

interface Square {
  kind: 'square';
  sideLength: number;
}

type Shape = Circle | Square;

// Function that computes the area based on the shape type
function computeArea(shape: Shape): number {
  switch (shape.kind) {
    case 'circle':
      return Math.PI * shape.radius * shape.radius;
    case 'square':
      return shape.sideLength * shape.sideLength;
    default:
      // TypeScript ensures that the switch is exhaustive by checking all possible cases
      throw new Error('Unknown shape!');
  }
}

// Example usage
const circle: Shape = { kind: 'circle', radius: 5 };
const square: Shape = { kind: 'square', sideLength: 4 };

const circleArea = computeArea(circle); // 78.53981633974483
const squareArea = computeArea(square); // 16

In this example, we have a discriminated union Shape, which represents two different shapes: Circle and Square. Each shape has a kind property, which acts as the discriminant. Based on the kind property, we use a switch statement in the computeArea function to determine the shape type and perform the corresponding area calculation.

TypeScript's type checker ensures that the switch statement is exhaustive, meaning all possible cases of the discriminated union are handled. This guarantees that you won't accidentally miss any variants of the union, leading to more reliable and safer code.

By leveraging discriminated unions and extracting members based on the discriminant property, you can create cleaner and more maintainable code when working with different variants or states in your TypeScript applications.

Also, the Extract utility type is used to extract members of a discriminated union based on specific criteria. In this context, we can use Extract to filter out the members of the Event discriminated union that match a particular value of the type property.