npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

rematch

v0.1.3

Published

Pattern matching for JavaScript/TypeScript

Downloads

399

Readme

Rematch npm version Build Status

Rematch is a pattern matching library built for JavaScript and TypeScript. Pattern matching helps you write safer, more readable, and more concise code.

Try it now

npm install rematch

Or download a release and pick up lib/rematch.js.

Basic usage

function dangerLevel(mutant) {
  return Rematch(mutant, [
    Rematch.Type(Villain, () => 5),
    Rematch.Value(Mutants.Flash, () => 0),
    Rematch.Value(Mutants.Superman, () => 2)
  ]);
};

console.log([
    dangerLevel(Mutants.Flash), // 0
    dangerLevel(Mutants.Superman), // 2
    dangerLevel(Mutants.Joker) // 5
])

console.log(dangerLevel(Mutants.Batman)) // Error: Rematch.MatchError

Play with it live on RunKit.

API

The Rematch function takes in an argument and a group of cases to test the argument against.

There are 4 types of cases:

  • Value - argument matches single value
  • Values - argument matches one of multiple values
  • Type - argument matches a type
  • Else - argument does not match any previous cases

If no cases are valid, a Rematch.MatchError is thrown. There are no 'fall-throughs' like in switch statements.

Advanced

By default, equality checks use lodash.isEqual, which does a structural comparison. You can override this by setting Rematch.isEqual to a custom value.

Why use pattern matching over if/else?

For the large majority of code that isn't performance-sensitive, there are a lot of great reasons why you'd want to use pattern matching over if/else:

  • it enforces a common return value and type for each of your branches (when using type definitions)
  • in languages with exhaustiveness checks, it forces you to explicitly consider all cases and noop the ones you don't need
  • it prevents early returns, which become harder to reason about if they cascade, grow in number, or the branches grow longer than the height of your screen (at which point they become invisible). Having an extra level of indentation goes a long way towards warning you you're inside a scope.
  • it can help you identify logic to pull out, rewriting it into a more DRY, debuggable, and testable form.

A longer example

Let's do an example! We're building a webapp, and we need to authenticate our users and update them on their status. Here's a straightforward solution:

if(user instanceof BlacklistedUser) {
  warnBlacklistMonitor();
  
  return;
}
else if(user.password === enteredPassword) {
  login();
  
  alert("You're logged in!");
}
else {
  onUserFailedLogin();
  
  alert("Mistyped your password?  Try again or do a password reset.");
}

This code works. Let's see how a pattern matching solution stacks up:

Rematch(user, [
  Rematch.Type(BlacklistedUser, () => warnBlacklistMonitor()),
  Rematch.Else(() => {
    var statusMessage = Rematch(enteredPassword, [
      Rematch.Value(user.password, () => {
        login();    
         
        return "You're logged in!";
      }),
      Rematch.Else(() => {
        onUserFailedLogin();
     
        return "Entered password is invalid";
      })
    ]);
    
    alert(statusMessage);
  }) 
])

It's immediately clear that there are 3 return points, and that 2 of them are dependent on the other one. We've identified a common variable statusMessage, which'll make debugging / testing easier down the line. And lastly, all the return points consistently return nothing.