03open 25 min

Enums and pattern matching: explicit state instead of ad hoc object shapes

Replace flexible tagged-object habits with Rust enums and exhaustive matching.

by the end of this lesson you can

  • Uses an enum for the variants
  • Models variant data explicitly
  • Uses matching rather than ad hoc property checks

Overview

JavaScript applications often represent state with objects that happen to include a `type` field or a combination of optional properties. Rust prefers enums that make the possible states explicit and checkable.

In JavaScript/Node, you often

represent variants with objects, string tags, and runtime checks that hope every shape is handled.

In Rust, the common pattern is

to model variants with enums and use `match` so the compiler can verify every state is considered.

why this difference matters

This is one of Rust's most powerful design tools. It turns vague runtime conventions into an explicit model the compiler can enforce.

JavaScript/Node

if (result.type === "ok") {
  return result.value;
}

Rust

match result {
    ResultState::Ok(value) => value,
    ResultState::Err(error) => return Err(error),
}

Deeper comparison

JavaScript/Node version

const response = { type: "loading" };

Rust version

enum ResponseState {
    Loading,
    Ready(Data),
    Failed(String),
}

Reflect

What gets easier when impossible state combinations stop being representable in the first place?

what a strong answer notices

A strong answer mentions fewer defensive checks, clearer UI or workflow logic, and stronger guarantees during refactors.

Rewrite

Rewrite this tagged-object JavaScript state model into a Rust enum plus pattern matching.

Rewrite this JavaScript/Node

const status = { type: "failed", message: "timeout" };

what good looks like

  • Uses an enum for the variants
  • Models variant data explicitly
  • Uses matching rather than ad hoc property checks

Practice

Design a Rust state model for an API request that can be loading, ready with data, or failed with an error message.

success criteria

  • Makes every state explicit
  • Shows how `match` would consume the model
  • Avoids recreating a loose JavaScript object convention

Common mistakes

  • Keeping JavaScript-style tagged objects instead of using enums.
  • Using `match` mechanically without designing the enum well first.
  • Leaving impossible combinations representable because that felt normal in JavaScript.

takeaways

  • This is one of Rust's most powerful design tools. It turns vague runtime conventions into an explicit model the compiler can enforce.
  • A strong answer mentions fewer defensive checks, clearer UI or workflow logic, and stronger guarantees during refactors.
  • Makes every state explicit