A comprehensive comparison library, for use in test frameworks
—
tcompare provides eight different comparison functions, each implementing a specific matching strategy. All functions return a Result object containing both the boolean match result and a detailed diff string.
All comparison functions return the same Result interface.
interface Result {
/** whether or not the objects are a satisfying match */
match: boolean;
/** Diff of formatted test object and expected pattern. Only shows properties which differ, not the entire object. */
diff: string;
}
type CompareOptions = FormatOptions & Pick<SameOptions, 'diffContext'>;Deep equivalence comparison with loose matching. Ensures all items in the pattern are found in the object and vice versa, using type coercion (e.g., 1 matches '1').
/**
* Deep equivalence comparison with loose matching
* @param obj - The object to test
* @param pattern - The expected pattern
* @param options - Comparison and formatting options
* @returns Result with match status and diff
*/
function same(obj: any, pattern: any, options?: CompareOptions): Result;Usage Examples:
import { same } from "tcompare";
// Loose equality - passes with type coercion
const result1 = same([1, 2, 3], ["1", "2", "3"]);
console.log(result1.match); // true
// Object comparison
const result2 = same(
{ name: "Alice", age: 25 },
{ name: "Alice", age: "25" }
);
console.log(result2.match); // true - age coerced from string to numberDeep equality comparison without type coercion. All items must match strictly, objects must have the same constructors, and no type coercion is performed.
/**
* Deep equality comparison without type coercion
* @param obj - The object to test
* @param pattern - The expected pattern
* @param options - Comparison and formatting options
* @returns Result with match status and diff
*/
function strict(obj: any, pattern: any, options?: CompareOptions): Result;Usage Examples:
import { strict } from "tcompare";
// Strict equality - fails without type coercion
const result1 = strict([1, 2, 3], ["1", "2", "3"]);
console.log(result1.match); // false
// Must match exactly including constructors
const result2 = strict(new Date("2023-01-01"), new Date("2023-01-01"));
console.log(result2.match); // trueSubset matching with loose comparison. Ensures all items in the pattern are found in the object, but ignores additional items in the object. Uses loose matching like same.
/**
* Subset matching with loose comparison
* @param obj - The object to test
* @param pattern - The pattern that must be present in the object
* @param options - Comparison and formatting options
* @returns Result with match status and diff
*/
function has(obj: any, pattern: any, options?: CompareOptions): Result;Usage Examples:
import { has } from "tcompare";
// Object with extra properties still matches
const result1 = has(
{ name: "Alice", age: 25, city: "NYC" },
{ name: "Alice", age: "25" }
);
console.log(result1.match); // true - extra 'city' field ignored
// Array subset matching
const result2 = has([1, 2, 3, 4], [1, 2]);
console.log(result2.match); // true - extra elements ignoredSubset matching with strict comparison for primitive values. Like has but uses strict equality for primitives while allowing constructor differences for objects.
/**
* Subset matching with strict comparison
* @param obj - The object to test
* @param pattern - The pattern that must be present in the object
* @param options - Comparison and formatting options
* @returns Result with match status and diff
*/
function hasStrict(obj: any, pattern: any, options?: CompareOptions): Result;Usage Examples:
import { hasStrict } from "tcompare";
// Strict matching for primitives
const result1 = hasStrict(
{ name: "Alice", age: 25 },
{ name: "Alice", age: "25" }
);
console.log(result1.match); // false - age string vs number
// Object matching allows constructor differences
const result2 = hasStrict(
new URL("https://example.com/path"),
{ pathname: "/path" }
);
console.log(result2.match); // trueThe most flexible matching strategy. Supports multiple pattern types including regular expressions, constructors, and string matching. Ideal for loose validation scenarios.
/**
* Flexible pattern matching with support for regex, constructors, and string patterns
* @param obj - The object to test
* @param pattern - The pattern to match (can be regex, constructor, string, etc.)
* @param options - Comparison and formatting options
* @returns Result with match status and diff
*/
function match(obj: any, pattern: any, options?: CompareOptions): Result;Usage Examples:
import { match } from "tcompare";
// Regular expression matching
const result1 = match("hello world", /^hello/);
console.log(result1.match); // true
// Constructor matching
const result2 = match(42, Number);
console.log(result2.match); // true
// String substring matching
const result3 = match("hello world", "world");
console.log(result3.match); // true
// Date string parsing
const result4 = match(new Date("2023-01-01"), "2023-01-01");
console.log(result4.match); // true
// Complex object with pattern matching
const result5 = match(
{ name: "Alice", age: 25, email: "alice@example.com" },
{ name: String, age: Number, email: /@example\.com$/ }
);
console.log(result5.match); // trueUses the flexible matching from match but requires that only the specified fields in the pattern are present in the object. Extra fields cause failure unless they're null or undefined.
/**
* Pattern matching with strict object shape requirements
* @param obj - The object to test
* @param pattern - The exact pattern the object must match
* @param options - Comparison and formatting options
* @returns Result with match status and diff
*/
function matchOnly(obj: any, pattern: any, options?: CompareOptions): Result;Usage Examples:
import { matchOnly } from "tcompare";
// Fails due to extra field
const result1 = matchOnly(
{ name: "Alice", age: 25, city: "NYC" },
{ name: String, age: Number }
);
console.log(result1.match); // false - 'city' field not allowed
// Passes with exact shape
const result2 = matchOnly(
{ name: "Alice", age: 25 },
{ name: String, age: Number }
);
console.log(result2.match); // trueLike match but fails when two values are loosely equal but not strictly equal (a == b && !(a === b)).
/**
* Flexible pattern matching without type coercion
* @param obj - The object to test
* @param pattern - The pattern to match
* @param options - Comparison and formatting options
* @returns Result with match status and diff
*/
function matchStrict(obj: any, pattern: any, options?: CompareOptions): Result;Usage Examples:
import { matchStrict } from "tcompare";
// Regular expression still works
const result1 = matchStrict("hello world", /^hello/);
console.log(result1.match); // true
// But strict equality is enforced for simple comparisons
const result2 = matchStrict(1, "1");
console.log(result2.match); // false - no type coercionCombines the strict shape requirements of matchOnly with the strict equality requirements of matchStrict.
/**
* Strict pattern matching with strict object shape requirements
* @param obj - The object to test
* @param pattern - The exact pattern the object must match strictly
* @param options - Comparison and formatting options
* @returns Result with match status and diff
*/
function matchOnlyStrict(obj: any, pattern: any, options?: CompareOptions): Result;Usage Examples:
import { matchOnlyStrict } from "tcompare";
// Most restrictive comparison - exact shape and strict values
const result = matchOnlyStrict(
{ name: "Alice", age: 25 },
{ name: "Alice", age: 25 }
);
console.log(result.match); // true
// Fails on both extra fields and type coercion
const result2 = matchOnlyStrict(
{ name: "Alice", age: "25", city: "NYC" },
{ name: "Alice", age: 25 }
);
console.log(result2.match); // falseChoose the right comparison function based on your needs:
same: Full deep equality with type coercion (most permissive)strict: Full deep equality without type coercionhas: Subset matching with type coercion (good for partial validation)hasStrict: Subset matching without type coercionmatch: Pattern-based matching (regex, constructors, strings)matchOnly: Pattern matching with exact object shapematchStrict: Pattern matching without type coercionmatchOnlyStrict: Most restrictive - exact shape and strict patternsInstall with Tessl CLI
npx tessl i tessl/npm-tcompare