TypeScript: Using Union Types and Arrays

Updated: January 7, 2024 By: Guest Contributor Post a comment

Introduction

TypeScript enhances JavaScript by adding types to the language. One of its most powerful features is the ability to use union types, which allow variables to store values of multiple types. Coupled with arrays, union types open a world of possibilities for developers to write robust and flexible code. This tutorial will dive into the subtleties of using union types and arrays in TypeScript through practical examples, paving the way from basics to more advanced concepts.

Basics of Union Types

Union types are a fundamental concept in TypeScript. They let you define a variable which can be one of several types. Let’s start with a simple example:

let userID: string | number;
userID = 'user123';
userID = 456;

In the above code snippet, the userID variable can be either a string or a number.

Union Types with Arrays

Arrays in TypeScript can also leverage union types, which allows storing multiple types of values in a single array. Here’s a basic example:

let mixedArray: (string | number)[];
mixedArray = ['Dave', 30, 'Meg', 45];

Here, mixedArray can hold both strings and numbers.

TypeScript and Functions

Union types become particularly useful when working with functions. You can accept multiple types of arguments and return multiple types of values.

function getLength(input: string | Array<any>): number {
  return input.length;
}

The getLength function can take either a string or an array and will return the length irrespective of the input type.

Advanced Union Types and Arrays

As we start dealing with more complex scenarios, TypeScript’s union types show their true strength. For instance, you can use them with tuples for precise type control in arrays:

type StringNumberPair = [string, number];
let pairArray: StringNumberPair[];
pairArray = [['Tom', 1], ['Jenny', 2]];

This defines an array of tuples where the first element is a string and the second a number.

Type Guards and Discriminated Unions

Type guards are a way to provide more information to the compiler about what type a union variable can be. Discriminated unions take this concept further and are beneficial when you’re working with several union types that could have a shared structure.

interface Car {
  type: 'car';
  drive(): void;
}

interface Boat {
  type: 'boat';
  sail(): void;
}

let vehicle: Car | Boat;

function operate(vehicle: Car | Boat): void {
  if (vehicle.type === 'car') {
    vehicle.drive();
  } else {
    vehicle.sail();
  }
}

This snippet employs a common property type in both interfaces to discriminate the union and calls the appropriate method based on its value.

Generics with Union Types

TypeScript generics add another layer of versatility, especially when mixed with union types. Generics allow you to write reusable and flexible functions and components. Below is an example using generics with union types:

function getFirstElement<T>(arr: T[]): T | undefined {
  return arr[0];
}

let numbersOrStrings = ['One', 'Two', 'Three', 4];
let element = getFirstElement(numbersOrStrings);

With generics, getFirstElement can work with any array type, preserving the union of types contained within the parameter array.

Conclusion

Union types, when combined with arrays in TypeScript, offer developers a powerful tool to write explicit and dynamic code that can adapt to various data structures. From basic usage to intricate patterns with generics and discriminated unions, mastering this aspect of TypeScript will elevate your coding skill to new heights. Embrace the flexibility and power of union types and arrays to make your software robust and type-safe.