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 🙏

© 2026 – Pkg Stats / Ryan Hefner

match-kit

v0.7.2

Published

Introduce pattern matching to TypeScript.

Readme

🎯 Match-Kit

A lightweight, flexible and powerful pattern matching library for JavaScript/TypeScript.

📦 Installation

npm install match-kit

🚀 Quick Start

import { match, Some, None, any, not, regex, when } from 'match-kit';

const greeting = 'hello';

const result = match(greeting, {
  hello: () => 'Exact match! 💯',
  [when(v => typeof v === 'string')]: () => 'Custom predicate match! 🎯',
  [when(greeting.length > 3)]: () => 'Boolean condition met! 🟢',
  [any('hi', 'hey')]: () => 'Multiple values match! 🔢',
  [not('bye', 'goodbye')]: () => 'Not "bye" or "goodbye" 🚫',
  [regex('^h.*o$')]: () => 'Regular expression match! 🔍',
  'h*o': () => 'Wildcard match! ✨',
  [Some]: () => 'Has some value! ✅',
  [None]: () => 'Has no value! ❌',
  _: () => 'Default case 🤷‍♂️',
});

console.log(result);

🧩 Features

  • Some/None Matching: Check for presence or absence of a value
  • 💯 Exact Value Matching: Match exact string, number, boolean values
  • 🎯 Custom Predicate Matching: Match using custom predicate functions or boolean values
  • 🔢 Multiple Value Matching: Match against multiple possible values
  • 🚫 Negation Matching: Match when value is NOT one of specified values
  • 🔍 Regular Expression Matching: Match using regex patterns
  • Wildcard Matching: Simple wildcard patterns with * and ?
  • 🔤 Case Sensitivity Control: Configure case sensitivity of string matching

📖 API Reference

Core Functions

match<R>(value, patterns, options?): R

Main pattern matching function that evaluates a value against multiple patterns and returns the result of the matching pattern handler.

Parameters:

  • value: The value to match (string, number, boolean, null, undefined)
  • patterns: Object mapping patterns to handler functions
  • options: Optional configuration
    • caseSensitive: Boolean (default: true)

Returns:

  • The result of the first matching pattern handler

ifLet<R>(value, pattern, handler): R | undefined

Conditionally execute a handler if the value matches the pattern.

Parameters:

  • value: The value to match
  • pattern: The pattern to match against
  • handler: Function to execute if match is successful

Returns:

  • Result of handler if matched, otherwise undefined

matches(value, pattern, options?): boolean

Check if a value matches a pattern without executing a handler.

Parameters:

  • value: The value to match
  • pattern: The pattern to match against
  • options: Optional configuration
    • caseSensitive: Boolean (default: true)

Returns:

  • Boolean indicating whether the value matches the pattern

Pattern Helpers

when(condition: ((value) => boolean) | boolean): string

Create a custom predicate pattern.

  • If a function is provided, the handler will be matched only if the function returns true for the input value. This is useful for advanced or flexible matching logic based on the value itself.
  • If a boolean is provided, the handler will be matched if the boolean is true. This is useful for incorporating pre-calculated conditions or simple boolean flags into the matching logic.
// Using a predicate function
match(value, {
  [when(v => typeof v === 'string' && v.length > 5)]: () => {
    console.log('String longer than 5 characters!');
  }
});

// Using a boolean value
match(value, {
  [when(typeof value === 'string' && value.length > 5)]: () => {
    console.log('String longer than 5 characters!');
  }
});

any(...values): string

Create a pattern that matches if the value equals any of the provided values.

match(value, {
  [any('apple', 'banana', 'cherry')]: () => 'This is a fruit!'
})

not(...values): string

Create a pattern that matches if the value does NOT equal any of the provided values.

match(value, {
  [not('red', 'blue', 'green')]: () => 'This is not a primary color!'
})

regex(pattern, flags?): string

Create a pattern that matches if the value matches the given regular expression.

match(value, {
  [regex('^[0-9]+$')]: () => 'This is a number!',
  [regex('^[A-Z]+$', 'i')]: () => 'This contains only letters!'
})

Special Patterns

Some

Matches any value that is not null or undefined.

match(value, {
  [Some]: () => 'Value exists!'
})

None

Matches null or undefined values.

match(value, {
  [None]: () => 'No value provided!'
})

_ (underscore)

Default case that matches if no other pattern matches.

match(value, {
  // other patterns...
  _: () => 'Default fallback'
})

🌟 Examples

Basic Value Matching

// String matching
const fruit = 'apple';
const fruitResult = match(fruit, {
  apple: () => '🍎 This is an apple',
  banana: () => '🍌 This is a banana',
  orange: () => '🍊 This is an orange',
  _: () => '❓ Unknown fruit'
});

// Number matching
const score = 85;
const grade = match(score, {
  [any(90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100)]: () => 'A 🎉',
  [any(80, 81, 82, 83, 84, 85, 86, 87, 88, 89)]: () => 'B 👍',
  [any(70, 71, 72, 73, 74, 75, 76, 77, 78, 79)]: () => 'C 😐',
  [any(60, 61, 62, 63, 64, 65, 66, 67, 68, 69)]: () => 'D 😕',
  _: () => 'F 😢'
});

Regex and Wildcard Matching

const input = 'hello123';

const result = match(input, {
  [regex('^[a-z]+$')]: () => 'Only letters',
  [regex('^[0-9]+$')]: () => 'Only numbers',
  [regex('^[a-z]+[0-9]+$')]: () => 'Letters followed by numbers',
  'hello*': () => 'Starts with hello',
  _: () => 'No pattern matched'
});
// Result: 'Letters followed by numbers'

Using when with a boolean condition

const isAuthenticated = true;
const userRole = 'editor';

const permission = match(userRole, {
  [when(isAuthenticated && userRole === 'admin')]: () => 'Full Access',
  [when(isAuthenticated && userRole === 'editor')]: () => 'Can Edit Content',
  [when(isAuthenticated)]: () => 'Logged In, Basic Access',
  _: () => 'Guest Access'
});
// Result: 'Can Edit Content'

Option Objects and Case-Insensitive Matching

const command = 'HELP';

const result = match(command, {
  help: () => 'Displaying help information',
  exit: () => 'Exiting the program',
  version: () => 'Current version: 1.0.0',
  _: () => 'Unknown command'
}, { caseSensitive: false });
// Result: 'Displaying help information' (despite case difference)

Using ifLet for Conditional Logic

const username = getUserInput(); // Could be a string or undefined

const welcomeMessage = ifLet(username, Some, () => {
  return `Welcome back, ${username}!`;
}) || 'Welcome, guest!';

Handling Optional Values

const data = fetchData(); // Could return null if fetch failed

const displayResult = match(data, {
  [Some]: () => `Data loaded: ${processData(data)}`,
  [None]: () => 'Failed to load data. Please try again.'
});

🎭 Pattern Matching Priority

When multiple patterns could match a value, the following priority rules apply:

  1. Some and None special patterns take highest priority
  2. Exact matches (string/number/boolean)
  3. when predicate patterns (both function and boolean variants)
  4. any and not composite value patterns
  5. Regular expression patterns (regex)
  6. Wildcard patterns (*, ?, with fewer wildcards having higher priority)
  7. Default case (_) has the lowest priority

⚠️ Error Handling

If no pattern matches and no default case (_) is provided, an error will be thrown:

// This will throw an error if value doesn't match any pattern
const result = match(value, {
  pattern1: () => 'Result 1',
  pattern2: () => 'Result 2'
  // No default case!
});

🤔 When to Use

Pattern matching is particularly useful for:

  • 🌳 Handling complex conditional logic more elegantly than if/else chains
  • 🎮 Processing user input and commands
  • 🧠 Implementing state machines
  • 🔄 Transforming data based on various conditions
  • ⚙️ Processing configuration options

📄 License

MIT