leven
Fast, dependency-free Levenshtein distance calculation for comparing and matching strings in JavaScript.
Repository Health
Technical Analysis
leven computes the Levenshtein distance between two strings — the minimum number of single-character edits (insertions, deletions, substitutions) needed to turn one string into another — using what its README describes as the fastest JavaScript implementation of the algorithm. It optimizes the classic dynamic-programming approach with prefix/suffix trimming and character-code caching to avoid redundant work, and supports an optional maxDistance cap that lets calls short-circuit once the distance is known to exceed a caller-specified threshold, which matters when the caller only cares about matches within a certain range.
Beyond the core leven() function, the package exports a closestMatch() helper that finds the nearest string in an array of candidates, itself using the same maxDistance-based pruning to skip candidates that can’t possibly beat the current best match. The library ships as a single dependency-free ESM module by Sindre Sorhus, widely used as a building block for fuzzy string matching, typo suggestion (“did you mean?”), and text-similarity scoring across the npm ecosystem.
What You Get
- A single leven(first, second, options?) function returning the edit distance as a number
- A closestMatch(target, candidates, options?) helper for finding the nearest string in a list of candidates
- An optional maxDistance cap that short-circuits calculation for large-scale comparisons
- Hand-written TypeScript type definitions (index.d.ts) with zero runtime dependencies
Common Use Cases
- Suggesting “did you mean?” corrections for CLI commands or search queries
- Fuzzy-matching user input against a list of valid options
- Deduplicating near-identical strings in datasets
- Scoring text similarity for autocomplete or search ranking
Under The Hood
Architecture leven ships as a single flat ESM module (index.js) with no internal layering — the default export leven() implements the classic Levenshtein dynamic-programming algorithm directly, using module-level scratch arrays (array and characterCodeCache) that are reused and re-sliced across calls rather than reallocated each time, and applying prefix/suffix trimming (dropping characters common to both strings from the front and back) before the DP loop even starts. The named export closestMatch() sits directly on top of leven(), delegating all distance computation to it while adding its own control flow: it deduplicates candidates via a Set, prunes candidates whose length difference already exceeds the current best distance, and passes an adaptive maxDistance cap into leven() that tightens as a closer candidate is found, short-circuiting the DP loop’s row scan whenever every value in the current row already exceeds the cap. There’s no dependency injection or external data flow — everything is synchronous, in-memory string comparison — so the one place a change to the core DP algorithm would ripple is directly into closestMatch()‘s pruning logic, since it assumes leven()‘s maxDistance-capped return value.
Tech Stack The package targets pure ESM (type: module, exports: ./index.js) with hand-written TypeScript declarations in index.d.ts rather than a compiled build step — there’s no bundler or transpiler in the pipeline. Runtime dependencies are zero; devDependencies split between the toolchain (ava for testing, xo for zero-config ESLint-based linting, tinybench for micro-benchmarking) and a set of competing Levenshtein implementations pulled in solely so bench.js can benchmark leven against them. Node engine support spans ^12.20.0, ^14.13.1, and >=16.0.0, and CI (.github/workflows/main.yml) runs npm test — xo then ava — on Node 16 for every push and pull request.
Code Quality test.js exercises the library extensively through ava, covering the base algorithm across ASCII and multi-byte (CJK) strings, an extensive maxDistance suite (early termination by length difference, row-minimum pruning, zero-cap and undefined/null options), and closestMatch’s tie-breaking and empty-candidate behavior. Linting is enforced via xo, an opinionated zero-config ESLint wrapper, and both xo and ava run in CI on every push/PR. Typing is provided via a hand-written index.d.ts rather than authoring the implementation in TypeScript, so type safety depends on the declaration file staying in sync with index.js rather than being compiler-enforced. Error handling is minimal by design — the library is pure computation with no I/O, so there’s nothing to catch or swallow — and edge cases (empty strings, identical strings, zero maxDistance) are handled explicitly and covered by tests.
API Design leven exposes exactly two functions with a minimal, symmetric API: leven(a, b, options?) returns a number, and closestMatch(target, candidates, options?) returns a string or undefined — no classes, no configuration objects to construct, no async surface. The maxDistance option is the one deliberate piece of API surface, and the same option threads through both functions so short-circuiting kicks in automatically wherever it’s supplied, rather than requiring a separate “bounded” variant. Getting started requires zero configuration — install, import the default export, call it — and the tradeoff against similar packages (several pulled in only as bench.js competitors) is squarely on raw speed via allocation reuse and early termination rather than richer features like weighted edit operations or diff output.
Used by 2 apps in this directory
Sanity
CMS
Open-source headless CMS with a fully customizable React Studio, real-time collaborative editing, structured content modeling, and GROQ query language
Scalar
Developer Tools
Beautiful, interactive OpenAPI documentation with a built-in offline-first API client and multi-language code generation — all in one open-source platform.