match-sorter

Simple, deterministic best-match sorting and filtering for arrays in JavaScript and TypeScript.

Library
npm
v8.3.0
4,105stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
50/100Fair
Development Activity12
Maintenance32
Community56
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
78/100Good
Architecture78
Code Quality82
Innovation68
Learning Curve85

match-sorter is a small, dependency-light TypeScript library that filters and ranks a list of items against a search value using a sensible, human-friendly ordering: case-sensitive equals first, then equals, starts-with, word-starts-with, contains, acronym, and finally a fuzzy in-order character match. Instead of a black-box relevance score from a fuzzy-search algorithm, it produces the ordering a person would expect when they type into a filter box.

It is commonly reached for behind autocomplete inputs, command palettes, and table/list filtering UIs where the list of candidate strings or objects lives entirely in memory (as opposed to a server-side search index). The library accepts plain strings or objects with configurable keys (including dot-notation nested paths, wildcard array paths, and per-key thresholds/min/max ranking overrides), and exposes both a simple matchSorter() that returns filtered/sorted items and a matchSorterWithRankInfo() that also surfaces the rank metadata used to produce that order.

What You Get

  • matchSorter() - filters and sorts an array of strings or objects against a query value in one call, returning only items that meet the ranking threshold, in best-match-first order
  • matchSorterWithRankInfo() - the same ranking behavior but returns each matched item alongside its rank, keyIndex, and the matched keyedValue for building custom UI (e.g. highlighting the matched key)
  • Configurable keys - rank objects by one or more properties, including dot-notation nested paths (name.first), wildcard array paths (aliases.*.name.first), and function-based value getters for interop with structures like Immutable.js
  • Per-key thresholds and min/max ranking overrides - pin a specific key to only match at a stricter threshold, or clamp its contribution with minRanking/maxRanking so one field can’t overrank or underrank the result
  • Exported rankings constants - the same threshold values (CASE_SENSITIVE_EQUAL through NO_MATCH) used internally are exported so consumers can pass a custom threshold or compare ranks themselves
  • Pluggable baseSort and sorter - override the tie-breaking comparator for same-rank items, or replace the sorting step entirely while keeping the ranking computation

Common Use Cases

  • Filtering a client-side autocomplete/typeahead dropdown as the user types
  • Powering a command palette (like a VS Code-style Cmd+K menu) where commands must surface in an intuitive order
  • Filtering rows of a data table or list against a free-text search box without a backend search index
  • Ranking select/combobox options (e.g. a country or tag picker) so the closest match appears first

Under The Hood

Architecture The entire library lives in a single module (src/index.ts) organized as a small pipeline rather than a class hierarchy: the two public entry points, matchSorter() and matchSorterWithRankInfo(), both delegate to a shared getRankedItems() that reduces the input array through getHighestRanking() for each item, which in turn calls getMatchRanking() per candidate key value and falls through an ordered chain of comparisons (exact, case-insensitive, starts-with, word-starts-with, contains, acronym) before handing off to getClosenessRanking() for the fuzzy in-order character-match score. Key resolution (getItemValues/getNestedValues/getAllValuesToRank) is a separate concern from ranking, so nested/wildcard object paths are flattened to plain string candidates before the same ranking logic runs on them. Because ranking and sorting are pure functions over immutable inputs with no shared mutable state, the core abstraction (the rankings hierarchy) could change without touching key-resolution or sorting code, and vice versa.

Tech Stack The package is authored entirely in TypeScript and ships pre-built dist/match-sorter.cjs.js, dist/match-sorter.esm.js, and dist/index.d.ts outputs, built via kcd-scripts build (Kent C. Dodds’ shared Babel/Rollup-based build tooling). Runtime dependencies are deliberately minimal: @babel/runtime (for compiled helper output) and remove-accents (for diacritic-insensitive matching). Linting, type-checking, and testing all run through the same kcd-scripts toolchain (lint, typecheck, test), and CI is wired up via a single GitHub Actions workflow (.github/workflows/validate.yml) that runs the validate script on every push/PR.

Code Quality Tests are extensive relative to the implementation size: src/__tests__/index.ts runs to roughly 750 lines against a ~570-line implementation, covering the ranking hierarchy, nested/wildcard key paths, threshold and min/max ranking overrides, custom baseSort/sorter functions, and diacritic handling with concrete input/output fixtures. Types are used throughout rather than bolted on afterward (RankingInfo, KeyOption, MatchSorterOptions are all exported), function names map directly to the ranking concepts described in the README, and the lint/typecheck/test scripts are enforced together via the validate script that CI runs on every change.

API Design The public surface is intentionally small: matchSorter(list, query) works with zero configuration on a plain array of strings, and the same call accepts an optional options.keys array to rank objects (including dot-notation and wildcard paths) without changing the return shape. Escape hatches are opt-in rather than required — threshold, keepDiacritics, baseSort, and sorter are all optional overrides layered on top of sensible defaults, and the exported rankings constants let consumers reference the same threshold values the library uses internally instead of guessing at magic numbers. Getting from “I have an array” to “a correctly filtered and ordered array” requires exactly one function call in the common case.

Used by 10 apps in this directory

JavaScript
90%
Other

CodeSandbox

Code Editors · Developer Tools

13,640

Instantly ready browser-based IDE that runs full npm dependency resolution and transpilation entirely client-side, with no server needed.

View details
69
Repo Health
76
Technical
62
Dependency
Built with
JavaScript90%
Updated 1 weeks ago
TypeScript
71%
Other

highlight.io

Developer Tools · Analytics · Monitoring

9,372

Open-source full-stack monitoring that unifies session replay, error tracking, logging, and distributed tracing so you can stop context-switching between tools.

View details
69
Repo Health
78
Technical
65
Dependency
Built with
TypeScript71%
Go16%
Updated 2 weeks ago
TypeScript
99%
MIT

KeystoneJS

CMS · Developer Tools

9,969

The superpowered headless CMS for developers built with GraphQL and React

View details
91
Repo Health
81
Technical
64
Dependency
Built with
TypeScript99%
Updated 5 days ago
TypeScript
81%
MIT

LibreChat

Developer Tools · AI Assistants

42,871

Unite every major AI model in one self-hosted chat platform with agents, code execution, MCP tools, and enterprise authentication.

View details
93
Repo Health
81
Technical
65
Dependency
Built with
TypeScript81%
JavaScript18%
Updated today
TypeScript
86%
MIT

medusa

Ecommerce

36,163

The most flexible open-source commerce platform — build B2C, B2B, and marketplace applications with modular, composable commerce primitives.

View details
93
Repo Health
87
Technical
63
Dependency
Built with
TypeScript86%
JavaScript14%
Updated 2 days ago
JavaScript
63%
AGPL 3.0

overleaf

Collaboration · Productivity

18,090

Open-source, real-time collaborative LaTeX editor with sandboxed compilation and full TeXLive support for self-hosted academic and research teams.

View details
82
Repo Health
80
Technical
62
Dependency
Built with
JavaScript63%
TypeScript29%
Updated 1 months ago
Go
40%
Apache 2.0

Rill

Analytics · Data Engineering

2,867

The fastest BI tool for humans and agents — define metrics, models, and dashboards as code and query them instantly on ClickHouse or DuckDB.

View details
87
Repo Health
88
Technical
64
Dependency
Built with
Go40%
TypeScript37%
Svelte22%
Updated 2 days ago
TypeScript
99%
Other

Rowy

Low Code Platforms · Databases

6,840

Manage Firestore data in an Airtable-like spreadsheet UI and build Cloud Functions workflows directly in your browser—on your own GCP project.

View details
45
Repo Health
71
Technical
65
Dependency
Built with
TypeScript99%
Updated 1 years ago
TypeScript
99%
Apache 2.0

Trigger.dev

Automation · AI Development · Developer Tools

16,223

Build and deploy fully-managed AI agents and background jobs in TypeScript — with no timeouts, durable retries, real-time observability, and elastic scaling built in.

View details
90
Repo Health
9
Technical
63
Dependency
Built with
TypeScript99%
Updated today

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search