
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
fuzzy-names
Advanced tools
A powerful TypeScript library for fuzzy name matching that combines Levenshtein distance and phonetic similarity algorithms to provide accurate name matching capabilities.
A powerful TypeScript library for fuzzy name matching that combines Levenshtein distance and phonetic similarity algorithms to provide accurate name matching capabilities.
Using npm:
npm install fuzzy-names
Using yarn:
yarn add fuzzy-names
The main function for finding the best matching name in a list.
function search<T = MatchItem>(
input: string,
matchList: Array<T>,
options?: Partial<Options>
): T | null
input: string
search("John Doe") // Basic full name
search("Dr. John A. Doe Jr.") // Name with prefix and suffix
search("josé garcía") // Name with diacritics
search(" Mary Jane ") // Name with extra spaces
matchList: Array<T>
string[]Array<T>matchPath in options to specify the path to the name propertyT allows for any object structure// Simple string array
const stringList = [
"John Doe",
"Jane Smith",
"Bob Johnson"
];
// Object array with direct name property
const objectList = [
{ name: "John Doe", id: 1 },
{ name: "Jane Smith", id: 2 }
];
// Object array with nested name property
const nestedList = [
{ user: { profile: { name: "John Doe" }, id: 1 } },
{ user: { profile: { name: "Jane Smith" }, id: 2 } }
];
options?: Partial<Options>
matchPath: ReadonlyArray<number | string>
// Direct name property
search("John", objects, { matchPath: ["name"] })
// Nested name property
search("John", nested, { matchPath: ["user", "profile", "name"] })
// Array index access
search("John", arrays, { matchPath: ["names", 0] })
threshold: { distance?: number, phonetics?: number }
distance property:
phonetics property:
// Strict matching
search("John", names, {
threshold: {
distance: 2, // Allow only minor typos
phonetics: 6 // Require strong phonetic match
}
})
// Loose matching
search("John", names, {
threshold: {
distance: 8, // Allow more character differences
phonetics: 2 // Accept weaker phonetic matches
}
})
// Balanced matching
search("John", names, {
threshold: {
distance: 5, // Moderate character differences
phonetics: 4 // Moderate phonetic similarity
}
})
null if no match is found
const people = [
{ name: "John Doe", id: 1 },
{ name: "Jane Smith", id: 2 }
];
const result = search("Jon Doe", people, {
matchPath: ["name"],
threshold: { distance: 2, phonetics: 1 }
});
// Returns: { name: "John Doe", id: 1 }
Calculates both Levenshtein distance and phonetic similarity between two names.
function calculateMatchMetric(
queryName: string,
corpusName: string
): MatchMetric
queryName: The input name to comparecorpusName: The name to compare againstconst metric = calculateMatchMetric("John Doe", "Jon Doe");
// Returns: {
// levDistance: { firstName: 1, lastName: 0, middleName: 0, total: 1 },
// phoneticsMetric: 6
// }
Calculates the Levenshtein distance between two names, broken down by name parts.
function calculateLevenshteinDistance(
queryName: string,
corpusName: string
): LevDistance
queryName: The input name to comparecorpusName: The name to compare againstconst distance = calculateLevenshteinDistance("John A Doe", "Jon B Doe");
// Returns: {
// firstName: 1,
// middleName: 1,
// lastName: 0,
// total: 2
// }
Calculates phonetic similarity between two names using multiple algorithms.
function calculatePhoneticMetric(
inputName: string,
corpusName: string,
options?: CalculatePhoneticsMetricOptions
): number
inputName: The input name to comparecorpusName: The name to compare againstoptions: Optional configuration
returnAsPercentage: Return score as percentage instead of raw numberconst score = calculatePhoneticMetric("John Doe", "Jon Doe");
// Returns: 6 (or 100 if returnAsPercentage is true)
Normalizes a name string by removing special characters and standardizing format.
function normalizeName(name: string): string
name: The name string to normalizeconst normalized = normalizeName(" John Döe-Smith ");
// Returns: "john doe smith"
Splits a full name into its constituent parts.
function splitNameIntoParts(name: string): NameParts
name: The full name to splitconst parts = splitNameIntoParts("John Alan Doe");
// Returns: {
// firstName: "john",
// lastName: "doe",
// middleNames: ["alan"]
// }
interface NameParts {
firstName: string;
lastName: string;
middleNames: string[];
}
interface LevDistance {
firstName: number;
middleName: number;
lastName: number;
total: number;
}
interface MatchMetric {
levDistance: LevDistance;
phoneticsMetric: number;
}
type Options = {
readonly matchPath: ReadonlyArray<number | string>;
readonly threshold: {
phonetics?: number;
distance?: number;
};
}
import { search } from 'fuzzy-names';
const names = ["John Doe", "Jane Smith", "Bob Johnson"];
const result = search("Jon Doe", names);
// Returns: "John Doe"
import { search } from 'fuzzy-names';
const users = [
{ user: { name: "John Doe", id: 1 } },
{ user: { name: "Jane Smith", id: 2 } }
];
const result = search("Jon Doe", users, {
matchPath: ["user", "name"]
});
// Returns: { user: { name: "John Doe", id: 1 } }
import { search } from 'fuzzy-names';
const names = [
{ name: "José García" },
{ name: "François Dubois" }
];
const result = search("Jose Garcia", names, {
matchPath: ["name"]
});
// Returns: { name: "José García" }
import { search } from 'fuzzy-names';
const names = ["John Doe", "Jonathan Doe", "Jon Doe"];
const result = search("Johnny Doe", names, {
threshold: {
distance: 5, // Allow more character differences
phonetics: 2 // Require stronger phonetic similarity
}
});
// Returns: "Jonathan Doe"
The core functionality of this library revolves around the search function, which implements a sophisticated name matching algorithm combining both edit distance and phonetic similarity measures. This dual approach allows for highly accurate name matching that can handle variations in spelling, pronunciation, and formatting.
The search process follows these steps:
The Levenshtein distance algorithm measures the minimum number of single-character edits required to change one string into another. For example:
The library calculates this distance separately for each name part (first, middle, last) to provide more accurate matching for full names.
SoundEx is a phonetic algorithm that indexes names by sound as pronounced in English. It generates a code that remains the same for similar-sounding names:
For example:
Metaphone improves upon SoundEx by using more sophisticated rules that better handle English pronunciation patterns. It considers letter combinations and their positions:
For example:
Double Metaphone further enhances the Metaphone algorithm by:
This is particularly useful for names that might have different pronunciations or cultural origins. For example:
The search function combines these algorithms in the following way:
Initial Filtering:
Distance Scoring:
Phonetic Matching:
Final Ranking:
This multi-algorithm approach provides robust matching that can handle:
FAQs
A powerful TypeScript library for fuzzy name matching that combines Levenshtein distance and phonetic similarity algorithms to provide accurate name matching capabilities.
We found that fuzzy-names demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.