expressive-switch

Use switch statements with a custom comparison expression. Goodbye `switch(true)`!

Usage no npm install needed!

<script type="module">
  import expressiveSwitch from 'https://cdn.skypack.dev/expressive-switch';
</script>

README

Expressive Switch

Use switch statements with a custom comparison expression. Goodbye switch(true)!

Very small library with no dependencies.

const switchPair = require('expressive-switch');

// Set up the closure and return the helper functions
const [s, c] = switchPair();

const subject = "I love horses";

switch(s(testCase => subject.indexOf(testCase) > -1)) {
    case c('ducks'):
        // This one does't match
        console.log("Someone's talking about ducks");
        break;
    case c('horses'):
        // This one matches!
        console.log("Someone's talking about horses");
        break;
    default:
        // Fallback for no matches
        console.log("Who knows?");
}

Uses

Error checking

function handleError(error) {
    const [s, c] = switchPair();

    switch(s(cls => error instanceof cls)) {
        case c(NotFoundError):
            return 'Page not found!';
        case c(TypeError):
            return 'Provided the wrong type!'
        default:
            // Don't know what the problem is, throw it
            throw error;
    }
}

URL routing

function routeRequest(url) {
    const [s, c] = switchPair();
    let args;

    switch(s(regex => args = url.match(regex))) {
        case c(/^\/$/):
            return HomePageComponent();
        case c(/^\/photos\/([0-9]+)$/):
            return PhotographComponent({ photoId: args[1] });
        default:
            return PageNotFoundComponent();
    }
}

Shape checking

function castResponseObject(object) {
    // Alternative syntax - specify the subject and predicate separately
    const [shapeOf, hasKey] = switchPair((key, subject) => key in subject);

    switch(shapeOf(object)) {
        case hasKey('error'):
            return new Error(object.error);
        case hasKey('value'):
            return object.value;
        default:
            return object;
    }
}

How does it work?

s saves your predicate function in a closure and returns a symbol.

c calls the predicate function with the test case value and returns the same symbol if the predicate returns truthy.

As far as switch is concerned, it's dealing with a symbol. As far as case is concerned, it's dealing with that same symbol or null.

TC39 Proposal

What if this was more concise and part of the javascript core language?

function handleError(error) {
    switch(error instanceof case) {
        case NotFoundError:
            return 'Page not found!';
        case TypeError:
            return 'Provided the wrong type!'
        default:
            throw error;
    }
}

Maybe it could be!