MuTasim

match.

In JavaScript, we lack a native "matching" pattern construct, unlike languages such as Rust where "Matching Literals" provide a concise and elegant syntax. Consider the following Rust example:

matching.rs
let x = 1;

match x {
    1 => println!("one"),
    2 => println!("two"),
    3 => println!("three"),
    _ => println!("anything"),
}

This syntax is straightforward and aesthetically pleasing, a feature absent in JavaScript. Although there are libraries offering pattern matching in TypeScript/JavaScript, creating our own solution is not a daunting task and enhances our understanding. Let's delve into the issues with switch cases and ternary operators:

Using IIFE (Immediately Invoked Function Expressions) in JSX:

TestComponent.tsx
<div>
    {(() => {
        switch (status) {
            case 'loading':
                return <p>Loading...</p>;
            case 'success':
                return <MyComponent/>;
            case 'error':
                return <ErrorMessage/>;
        }
    })()
    }
</div>

Doesn't it look like clean code, yeah? Let's also look at the ternary operator

Nested Ternary Operators:

TestComponent.tsx
<div>
    {status === 'loading' ? (
        <p>Loading...</p>
    ): status === 'success' ? (
        <MyComponent/>
    ): status === 'error' ? (
        <ErrorMessage/>
    ): null}
</div>

The code is really hard to read. Just KISS

To address these challenges, let's implement a simple matching pattern utility:

./lib/utils.ts
export function match(value) {
    let result = null;

    return {
        with: function (pattern, action) {
            if (pattern === value) {
                result = action();
            }
            return this;
        },
        otherwise: (action) => {
            if (!result) {
                result = action();
            }
            return result;
        }
    };
}

How it works:

  • match takes a value and returns an object.
  • with checks if the provided pattern matches the value and performs the associated action.
  • otherwise defines an action for the default case if no pattern matches.

Now, let's use this utility to simplify our code (JSX):

TestComponent.tsx
<div>
    {match(status)
        .with('loading', () => <p>isLoading...</p>)
        .with('success', () => <MyComponent/>)
        .with('error', () => <ErrorMessage/>)
        .otherwise(() => <p>Default case</p>)
    }
</div>

Looks pretty, doesn't it? Yep, I also like it. This approach allows us to write matching patterns directly inside JSX, providing a cleaner and more readable alternative to switch cases or nested ternary operators.

Happy coding!