Skip to content

Equivalence

Defines reusable equality functions for values of the same type.

An Equivalence<A> returns true when two A values should be treated as the same for a particular purpose. This module includes strict equality instances for primitive types, constructors for custom comparisons, and helpers for tuples, arrays, structs, records, dates, and values compared through a derived field.

17 exports Added in v2.0.0 Source

Combinators

Record

Added in v4.0.0 Source

Creates an equivalence for objects by comparing all properties using the same equivalence.

When to use

Use when you need to compare records with the same equivalence for every property value.

Details

- Compares all properties present in both objects - Requires both objects to have the same set of keys; different keys result in false - All property values must be equivalent according to the provided equivalence - Supports both string and symbol keys via Reflect.ownKeys - Empty objects are considered equivalent - The result is also an equivalence that satisfies reflexive, symmetric, and transitive properties

Signature

declare function Record<A>(value: Equivalence<A>): Equivalence<Record<PropertyKey, A>>;

Struct

Added in v4.0.0 Source

Creates an equivalence for objects by comparing their properties using provided equivalences.

When to use

Use when you need an Equivalence for objects with known, fixed property names.

Details

Compares only the properties specified in the struct definition; other properties are ignored. String and symbol keys are supported via Reflect.ownKeys. The result returns true only if all specified properties are equivalent according to their equivalences, and it also satisfies reflexive, symmetric, and transitive properties.

See

Signature

declare function Struct<R extends Record<string, Equivalence<any>>>(
  fields: R,
): Equivalence<{ [K in string | number | symbol]: [R[K]] extends [Equivalence<A>] ? A : never }>;

Tuple

Added in v4.0.0 Source

Creates an equivalence for tuples with heterogeneous element types.

When to use

Use when you need an Equivalence for fixed-length tuples with per-position equivalences.

Details

Tuples must have the same length; different lengths are never equivalent. Each equivalence is applied to the corresponding element position. The result returns true only if all elements are equivalent according to their respective equivalences, and it also satisfies reflexive, symmetric, and transitive properties.

Signature

declare function Tuple<Elements extends readonly Array<Equivalence<any>>>(elements: Elements): Equivalence<{ [I in string | number | symbol]: [Elements[I]] extends [Equivalence<A>] ? A : never }>

Combining

combine

Added in v2.0.0 Source

Combines two equivalence relations using logical AND.

When to use

Use when you need to combine exactly two equivalences with AND semantics.

Details

Returns true only if both equivalences return true. The comparison short-circuits when the first equivalence returns false. The result is also an equivalence that satisfies reflexive, symmetric, and transitive properties.

See

Signature

declare const combine: {
  <A>(that: Equivalence<A>): (self: Equivalence<A>) => Equivalence<A>;
  <A>(self: Equivalence<A>, that: Equivalence<A>): Equivalence<A>;
};

combineAll

Added in v2.0.0 Source

Combines multiple equivalence relations into a single equivalence using logical AND.

When to use

Use when you need to combine many Equivalence instances from an iterable.

Details

Returns true only if all equivalences in the collection return true. The comparison stops at the first equivalence that returns false. Empty collections return an equivalence that always returns true. The result is also an equivalence that satisfies reflexive, symmetric, and transitive properties.

See

Signature

declare function combineAll<A>(collection: Iterable<Equivalence<A>>): Equivalence<A>;

Constructors

make

Added in v2.0.0 Source

Creates a custom equivalence relation with an optimized reference equality check.

When to use

Use when you need an equality rule that the built-in instances and input mapping helpers cannot express, and you can provide a law-abiding comparison.

Details

The returned equivalence first checks reference equality (===) for performance. If the values are not the same reference, it falls back to the provided equivalence function, which must satisfy reflexive, symmetric, and transitive properties.

See

Signature

declare function make<A>(isEquivalent: (self: A, that: A) => boolean): Equivalence<A>;

makeReducer

Added in v4.0.0 Source

Creates a Reducer for combining Equivalence instances, useful for aggregating equivalences in collections.

When to use

Use when you need a reducer that combines equivalences.

Details

Returns a reducer that combines equivalences using combine. The identity element for empty collections is an equivalence that always returns true. The reducer uses combineAll for collections of equivalences and can be used with fold operations.

See

Signature

declare function makeReducer<A>(): Reducer<Equivalence<A>>;

strictEqual

Added in v4.0.0 Source

Creates an equivalence relation that uses strict equality (===) to compare values.

When to use

Use when you need strict equality (===) as the comparison.

Details

Uses JavaScript's strict equality operator (===). Primitives compare by value. Objects compare by reference, so only the same object instance is equivalent. Use this as a building block for more complex equivalences via mapInput or combine.

Gotchas

NaN !== NaN, so NaN values are never considered equivalent.

See

  • make
  • Equal for structural equality

Signature

declare const strictEqual: <A>() => Equivalence<A>;

Instances

BigInt

Added in v4.0.0 Source

Equivalence instance for bigints using strict equality (===).

When to use

Use when you need to supply bigint equality.

Signature

declare const BigInt: Equivalence<bigint>;

Boolean

Added in v4.0.0 Source

Equivalence instance for booleans using strict equality (===).

When to use

Use when you need to supply boolean equality.

Signature

declare const Boolean: Equivalence<boolean>;

Date

Added in v2.0.0 Source

Equivalence instance for Date objects that compares their getTime() values using Equivalence.Number.

When to use

Use when you need an Equivalence for JavaScript date objects by their millisecond timestamp.

Details

Different Date instances that represent the same millisecond timestamp are equivalent. Because Equivalence.Number treats NaN as equal to NaN, two invalid Date values are also considered equivalent.

See

  • Number for the numeric equivalence applied to each Date#getTime() result
  • mapInput for deriving an equivalence by mapping inputs before comparison
  • strictEqual for reference equality when two values must be the same object

Signature

declare const Date: Equivalence<Date>;

Number

Added in v4.0.0 Source

Equivalence instance for numbers.

When to use

Use when you need numeric equality that treats NaN as equal to itself.

Signature

declare const Number: Equivalence<number>;

String

Added in v4.0.0 Source

Equivalence instance for strings using strict equality (===).

When to use

Use when you need to supply case-sensitive string equality.

Signature

declare const String: Equivalence<string>;

Mapping

mapInput

Added in v2.0.0 Source

Transforms an equivalence relation by mapping the input values before comparison.

When to use

Use when you need an equivalence for one type by comparing a derived value.

Details

- Applies the transformation function to both values before comparing - The transformation function should be pure and have no side effects - The resulting equivalence compares the transformed values using the provided equivalence - The result is also an equivalence that satisfies reflexive, symmetric, and transitive properties - Useful for comparing by one property or normalizing values before comparison, such as case-insensitive strings

See

Signature

declare const mapInput: {
  <B, A>(f: (b: B) => A): (self: Equivalence<A>) => Equivalence<B>;
  <A, B>(self: Equivalence<A>, f: (b: B) => A): Equivalence<B>;
};

Models

Equivalence type

Added in v2.0.0 Source

Represents an equivalence relation over type A.

When to use

Use as a type annotation when you accept or return an equivalence function.

Details

- Returns boolean: true if values are equivalent, false otherwise - Must satisfy reflexive, symmetric, and transitive properties

See

Signature

type Equivalence<in A> = (self: A, that: A) => boolean;

Other

Array

Added in v4.0.0 Source

Signature

declare function Array<A>(item: Equivalence<A>): Equivalence<readonly Array<A>>

Utility Types

EquivalenceTypeLambda interface

Added in v2.0.0 Source

Type lambda for Equivalence, used for higher-kinded type operations.

When to use

Use when you need to abstract over Equivalence in higher-kinded type code.

Details

- Enables Equivalence to work with the Effect type system's HKT infrastructure - Used internally for type-level computations and generic abstractions

See

Signature

interface EquivalenceTypeLambda extends TypeLambda {
  readonly type: Equivalence<unknown>;
}