How ts-pattern can improve your code readability?

Tauan Camargo - Sep 13 - - Dev Community

My First Encounter with ts-pattern

A few months ago, I was reviewing a client’s codebase filled with numerous switch statements and object literals spread across many files, which was making the readability and maintainability a mess.

During a pair programming session with my teammate Erick, he shared his screen and showed me a library that he was testing out.

That was my first experience with ts-pattern 🤩, and honestly, it blew my mind! The improvement in readability and maintainability was incredible.

Here is the link for ts-pattern documentation.

Let me show you some use cases where ts-pattern can make a real difference. One of the first questions I had was: Can I use this in any TypeScript project? The answer is YES 🙌.

Use cases

1. Replacing Complex Switch Statements

Traditional switch statement:

const status = "success";

let message;
switch (status) {
  case "success":
    message = "Operation was successful!";
    break;
  case "error":
    message = "There was an error.";
    break;
  default:
    message = "Unknown status.";
}
console.log(message);  // Output: Operation was successful!
Enter fullscreen mode Exit fullscreen mode

Using ts-pattern:

import { match } from 'ts-pattern';

const status = "success";

const message = match(status)
  .with("success", () => "Operation was successful!")
  .with("error", () => "There was an error.")
  .otherwise(() => "Unknown status.");

console.log(message);  // Output: Operation was successful!
Enter fullscreen mode Exit fullscreen mode

Comparison:

Readability using ts-pattern is clean, no need for break statements, and pattern matches focus directly on the cases. Adding or removing conditions in ts-pattern is easier, and you don’t have to deal with the traps of forgetting breaks in switch cases.

2. Object Matching for API Responses

Using object matching:

const apiResponse = {
  status: 200,
  data: {
    user: {
      id: 1,
      name: 'John',
    },
  },
};

let userName;
if (apiResponse.status === 200 && apiResponse.data.user.name === 'John') {
  userName = "Hello, John!";
} else {
  userName = "User not found.";
}

console.log(userName);  // Output: Hello, John!
Enter fullscreen mode Exit fullscreen mode

Using ts-pattern:

const apiResponse = {
  status: 200,
  data: {
    user: {
      id: 1,
      name: 'John',
    },
  },
};

const userName = match(apiResponse)
  .with({ status: 200, data: { user: { name: "John" } } }, () => "Hello, John!")
  .otherwise(() => "User not found.");

console.log(userName);  // Output: Hello, John!
Enter fullscreen mode Exit fullscreen mode

Comparison:

ts-pattern reduces the need for deeply nested if conditions, making the logic cleaner and smoother. The pattern matching directly reflects the structure of the object, making it easier to understand and modify.

3. State Management

State management using switch:

const appState = { status: "loading" };

let displayMessage;
switch (appState.status) {
  case "loading":
    displayMessage = "Loading...";
    break;
  case "success":
    displayMessage = "Data loaded successfully!";
    break;
  case "error":
    displayMessage = "Failed to load data.";
    break;
  default:
    displayMessage = "Unknown state.";
}

console.log(displayMessage);  // Output: Loading...
Enter fullscreen mode Exit fullscreen mode

Using ts-pattern:

const appState = { status: "loading" };

const displayMessage = match(appState.status)
  .with("loading", () => "Loading...")
  .with("success", () => "Data loaded successfully!")
  .with("error", () => "Failed to load data.")
  .otherwise(() => "Unknown state.");

console.log(displayMessage);  // Output: Loading...
Enter fullscreen mode Exit fullscreen mode

Comparison:

ts-pattern simplifies state management by eliminating the need for repetitive case and break statements. As the number of states grows, ts-pattern scales better with fewer chances of logical errors.

By comparing switch statements, object literals, and traditional conditionals with ts-pattern, it’s clear that ts-pattern offers a more elegant and scalable approach. Whether you’re handling complex states, object matching, or validations, ts-pattern reduces boilerplate code, improves readability, and minimizes potential bugs. Give it a try.

Will try to be more consistent in posting articles here 🤪. Thanks.

. . . . . . . . . . .
Terabox Video Player