TypeScript Type Aliases

A practical guide to TypeScript type aliases, union types, intersection types, and literal values.

TL;DR

  1. Declare custom type identifiers using the type keyword syntax.
  2. Combine multiple candidate shapes using union pipe | operators.
  3. Merge distinct object properties together using intersection & operators.

Type Alias Syntax

    type keyword

    Binds a custom name to any valid type expression.

    type Identifier = string | number;
    const userId: Identifier = 'usr_981';
    object type alias

    Defines structured object shapes with typed attributes.

    type Coordinate = {
      x: number;
      y: number;
    };
    const origin: Coordinate = { x: 0, y: 0 };
    tuple type alias

    Models fixed-length arrays with indexed type elements.

    type KeyValuePair = [string, number];
    const entry: KeyValuePair = ['port', 8080];

Union Types

    primitive union

    Permits values matching any of the specified types.

    type InputValue = string | number | boolean;
    let current: InputValue = 'active';
    narrowing with typeof

    Differentiates union members inside conditional logic.

    function printId(id: string | number) {
      if (typeof id === 'string') {
        console.log(id.toUpperCase());
      } else {
        console.log(id.toFixed(2));
      }
    }
    string literal union

    Restricts assignments to an enumerated set of strings.

    type Status = 'pending' | 'success' | 'failed';
    const requestStatus: Status = 'pending';

Intersection Types

    object intersection

    Merges multiple object contracts into a combined type.

    type Named = { name: string };
    type Aged = { age: number };
    type Person = Named & Aged;
    const sam: Person = { name: 'Sam', age: 28 };
    extending with &

    Appends additional fields onto an existing type alias.

    type User = { id: string; email: string };
    type Admin = User & { permissions: string[] };
    never resolution

    Evaluates incompatible primitive intersections to never.

    type Impossible = string & number; // never
    // let x: Impossible; // Cannot assign any value

Literal Types

    boolean literal

    Locks a type strictly to true or false values.

    type Truthy = true;
    const isVerified: Truthy = true;
    numeric literal

    Constrains numbers to explicit predefined constants.

    type HttpSuccess = 200 | 201 | 204;
    const statusCode: HttpSuccess = 200;
    as const assertion

    Infers deeply immutable literal types from objects.

    const config = {
      endpoint: '/api/v1',
      retries: 3
    } as const;

Generic Type Aliases

    generic type

    Accepts type arguments to build reusable container types.

    type Result<T> = {
      data: T;
      error?: string;
    };
    const response: Result<number> = { data: 42 };
    nullable helper

    Creates a reusable null or undefined wrapper type.

    type Nullable<T> = T | null | undefined;
    let cachedToken: Nullable<string> = null;
    function type alias

    Annotates reusable callback signatures concisely.

    type Predicate<T> = (item: T) => boolean;
    const isEven: Predicate<number> = (n) => n % 2 === 0;

Tips

  1. Use type aliases for primitives, unions, and intersections where interface syntax cannot be applied.
  2. Append as const to configuration objects to lock properties down into strict read-only literal types.

Warnings

  1. Remember that type aliases cannot undergo declaration merging, so declaring duplicate names throws a compiler error.
  2. Intersecting primitive types like string & number results in the uninhabitable never type rather than a combined value.

In Practice

FAQ