Order
Defines comparison functions for ordered values.
An Order<A> compares two A values and returns whether the first is less
than, equal to, or greater than the second. Orders are used for sorting,
choosing minimum or maximum values, checking ranges, and building ordered data
structures. This module includes built-in orders, constructors for custom
orders, tools for reversing and combining comparisons, tuple and struct
helpers, comparison predicates, clamping, and reducer support.
Combinators
Creates a new Order that reverses the comparison order of the input Order.
When to use
Use when you need the reverse of an existing order.
Details
Returns a new order that swaps the arguments before comparison. If the
original order returns -1, the flipped order returns 1, and vice versa.
Equal comparisons remain 0.
See
- combine to combine orders for multi-criteria comparison
Signature
declare function flip<A>(O: Order<A>): Order<A>Example
(Reversing an Order)
import { Order } from "effect"
const flip = Order.flip(Order.Number)
flip(1, 2) // => 1flip(2, 1) // => -1flip(1, 1) // => 0Creates an Order for structs by applying the given Orders to each property in sequence.
When to use
Use when you need multi-field ordering for objects with known properties.
Details
Compares structs field-by-field in the key order of the fields object and
stops at the first non-zero comparison result. Field order matters: earlier
fields take precedence. The result is 0 only if all fields are equal.
See
Signature
declare function Struct<R extends { [x: string]: Order<any>;}>(fields: R): Order<{ [K in string | number | symbol]: [R[K]] extends [Order<A>] ? A : never }>Example
(Ordering structs)
import { Order } from "effect"
const personOrder = Order.Struct({ name: Order.String, age: Order.Number})
const person1 = { name: "Alice", age: 30 }const person2 = { name: "Bob", age: 25 }const person3 = { name: "Alice", age: 25 }
personOrder(person1, person2) // => -1personOrder(person1, person3) // => 1personOrder(person1, person1) // => 0Creates an Order for a tuple type based on orders for each element.
When to use
Use when you need fixed-length tuple ordering with per-position orders.
Details
Compares tuples element-by-element using the corresponding order and stops at
the first non-zero comparison result. Tuples must have the same length as the
order collection, and the result is 0 only if all elements are equal.
See
- Array to compare arrays with length consideration
Signature
declare function Tuple<Elements extends readonly Array<Order<any>>>(elements: Elements): Order<{ [I in string | number | symbol]: [Elements[I]] extends [Order<A>] ? A : never }>Example
(Ordering tuples)
import { Order } from "effect"
const tupleOrder = Order.Tuple([Order.Number, Order.String])
tupleOrder([1, "a"], [2, "b"]) // => -1tupleOrder([1, "b"], [1, "a"]) // => 1tupleOrder([1, "a"], [1, "a"]) // => 0Combining
Combines two Order instances to create a new Order that first compares using the first Order,
and if the values are equal, then compares using the second Order.
When to use
Use when you need tie-breaking with exactly two orders.
Details
First applies the first order. If the result is non-zero, that result is
returned; otherwise, the second order is applied. The result is the first
non-zero comparison result, or 0 if both orders return 0.
See
- combineAll to combine multiple orders from a collection
- mapInput to transform orders to work with different types
Signature
declare const combine: { <A>(that: Order<A>): (self: Order<A>) => Order<A>; <A>(self: Order<A>, that: Order<A>): Order<A>;}Example
(Combining two Orders)
import { Order } from "effect"
const byAge = Order.mapInput( Order.Number, (person: { name: string; age: number }) => person.age)const byName = Order.mapInput( Order.String, (person: { name: string; age: number }) => person.name)const byAgeAndName = Order.combine(byAge, byName)
const person1 = { name: "Alice", age: 30 }const person2 = { name: "Bob", age: 30 }const person3 = { name: "Charlie", age: 25 }
byAgeAndName(person1, person2) // => -1byAgeAndName(person1, person3) // => 1combineAll
Combines all Order instances in the provided collection into a single Order.
The resulting Order compares using each Order in sequence until a non-zero result is found.
When to use
Use when you need tie-breaking across a variable number of orders.
Details
Applies orders in iteration order and short-circuits on the first non-zero
result. It returns 0 only if all orders return 0.
See
- combine to combine two orders
- makeReducer to create a reducer for combining orders
Signature
declare function combineAll<A>(collection: Iterable<Order<A>>): Order<A>Example
(Combining multiple Orders)
import { Order } from "effect"
const byAge = Order.mapInput( Order.Number, (person: { name: string; age: number }) => person.age)const byName = Order.mapInput( Order.String, (person: { name: string; age: number }) => person.name)
const combinedOrder = Order.combineAll([byAge, byName])
const person1 = { name: "Alice", age: 30 }const person2 = { name: "Bob", age: 30 }
combinedOrder(person1, person2) // => -1Comparisons
Restricts a value between a minimum and a maximum according to the given order.
When to use
Use when you need to clamp a value to an inclusive range according to an
Order.
Details
Returns the value itself when it is between minimum and maximum, inclusive. Values below the range return minimum, and values above the range return maximum. The minimum must be less than or equal to the maximum according to the order.
See
Signature
declare function clamp<A>(O: Order<A>): { (options: { maximum: A; minimum: A; }): (self: A) => A; (self: A, options: { maximum: A; minimum: A; }): A;}Example
(Clamping values)
import { Order } from "effect"
const clamp = Order.clamp(Order.Number)({ minimum: 1, maximum: 5 })
clamp(3) // => 3clamp(0) // => 1clamp(6) // => 5Returns the maximum of two values according to the given order. If they are equal, returns the first argument.
When to use
Use when you need to select the larger of two values according to an
Order.
Details
Returns the value that compares as greater than or equal to the other value. If values are equal, the first argument is returned.
See
Signature
declare function max<A>(O: Order<A>): { (that: A): (self: A) => A; (self: A, that: A): A;}Example
(Selecting the maximum value)
import { Order } from "effect"
const maxNumber = Order.max(Order.Number)
maxNumber(1, 2) // => 2maxNumber(2, 1) // => 2maxNumber(1, 1) // => 1Returns the minimum of two values according to the given order. If they are equal, returns the first argument.
When to use
Use when you need to select the smaller of two values according to an
Order.
Details
Returns the value that compares as less than or equal to the other value. If values are equal, the first argument is returned.
See
Signature
declare function min<A>(O: Order<A>): { (that: A): (self: A) => A; (self: A, that: A): A;}Example
(Selecting the minimum value)
import { Order } from "effect"
const minNumber = Order.min(Order.Number)
minNumber(1, 2) // => 1minNumber(2, 1) // => 1minNumber(1, 1) // => 1Constructors
alwaysEqual
Creates an Order that considers all values as equal.
When to use
Use when you need an order that treats all values as equal.
Details
Always returns 0 regardless of input values, making it useful as a neutral
element in order composition.
See
- combine to combine with other orders
Signature
declare function alwaysEqual<A>(): Order<A>Example
(Ordering with an always-equal Order)
import { Order } from "effect"
const alwaysEqualOrder = Order.alwaysEqual<number>()
alwaysEqualOrder(1, 2) // => 0alwaysEqualOrder(2, 1) // => 0alwaysEqualOrder(1, 1) // => 0Creates a new Order instance from a comparison function.
When to use
Use when you need a sorting rule not covered by the built-in orders or input mapping helpers, and you can provide a total comparison.
Details
Uses reference equality (===) as a shortcut: if self === that, it returns
0 without calling the comparison function. The comparison function should
return -1, 0, or 1, and the returned order satisfies total ordering
laws when the comparison function does.
See
Signature
declare function make<A>(compare: (self: A, that: A) => -1 | 0 | 1): Order<A>Example
(Creating an Order)
import { Order } from "effect"
const byAge = Order.make<{ name: string; age: number }>((self, that) => { if (self.age < that.age) return -1 if (self.age > that.age) return 1 return 0})
byAge({ name: "Alice", age: 30 }, { name: "Bob", age: 25 }) // => 1byAge({ name: "Alice", age: 25 }, { name: "Bob", age: 30 }) // => -1makeReducer
Creates a Reducer for combining Order instances, useful for aggregating orders in collections.
When to use
Use when you need a reducer that combines orders.
Details
Returns a reducer that combines orders using combine, uses alwaysEqual as
the identity element for empty collections, and uses combineAll for
combining collections of orders. The reducer can be used with fold operations
on collections.
See
- combine to combine two orders
- combineAll to combine multiple orders
- Reducer for reducing orders as a collection operation
Signature
declare function makeReducer<A>(): Reducer<Order<A>>Example
(Creating a Reducer)
import { Order } from "effect"
const reducer = Order.makeReducer<number>()const orders = [Order.Number, Order.flip(Order.Number)]
const combined = reducer.combineAll(orders)combined(1, 2) // => -1Instances
Order instance for bigints that compares them numerically.
When to use
Use when you need numeric ordering for bigint values.
Details
Uses standard numeric comparison for bigint values and handles arbitrarily large integers.
See
Signature
declare const BigInt: Order<bigint>Example
(Ordering BigInts)
import { Order } from "effect"
Order.BigInt(1n, 2n) // => -1Order.BigInt(2n, 1n) // => 1Order.BigInt(1n, 1n) // => 0Order instance for booleans where false is considered less than true.
When to use
Use when you need boolean ordering where false comes before true.
Details
false is less than true, and equal values return 0.
See
- mapInput to compare objects by a boolean property
Signature
declare const Boolean: Order<boolean>Example
(Ordering booleans)
import { Order } from "effect"
Order.Boolean(false, true) // => -1Order.Boolean(true, false) // => 1Order.Boolean(true, true) // => 0Order instance for Date objects that compares them chronologically by their timestamp.
When to use
Use when you need chronological ordering for JavaScript date values.
Details
Compares dates by their underlying timestamp in milliseconds since the epoch.
Earlier dates are less than later dates. Invalid dates are compared through
their getTime() result.
See
- mapInput to compare objects by a date property
Signature
declare const Date: Order<Date>Example
(Ordering Dates)
import { Order } from "effect"
const date1 = new Date("2023-01-01")const date2 = new Date("2023-01-02")
Order.Date(date1, date2) // => -1Order.Date(date2, date1) // => 1Order.Date(date1, date1) // => 0Order instance for numbers that compares them numerically.
When to use
Use when you need numeric ordering for numbers.
Details
0 is considered equal to -0. All NaN values are considered equal to
each other, and any NaN is considered less than any non-NaN number. All
other values use standard numeric comparison.
See
Signature
declare const Number: Order<number>Example
(Ordering numbers)
import { Order } from "effect"
Order.Number(1, 1) // => 0Order.Number(1, 2) // => -1Order.Number(2, 1) // => 1
Order.Number(0, -0) // => 0Order.Number(NaN, 1) // => -1Order instance for strings that compares them lexicographically using JavaScript's < operator.
When to use
Use when you need lexicographic string ordering.
Details
Uses lexicographic dictionary ordering. The empty string is less than any non-empty string, and comparisons are case-sensitive.
See
Signature
declare const String: Order<string>Example
(Ordering strings)
import { Order } from "effect"
Order.String("apple", "banana") // => -1Order.String("banana", "apple") // => 1Order.String("apple", "apple") // => 0Mapping
Transforms an Order on type A into an Order on type B by providing a function that
maps values of type B to values of type A.
When to use
Use when you need to adapt an Order to compare a larger value by one
derived property.
Details
Applies the mapping function to both values before comparison. The mapping function should be pure and not have side effects so the ordering properties of the original order are preserved.
See
Signature
declare const mapInput: { <B, A>(f: (b: B) => A): (self: Order<A>) => Order<B>; <A, B>(self: Order<A>, f: (b: B) => A): Order<B>;}Example
(Mapping Input)
import { Order } from "effect"
const byLength = Order.mapInput(Order.Number, (s: string) => s.length)
byLength("a", "bb") // => -1byLength("bb", "a") // => 1byLength("aa", "bb") // => 0Models
Represents a total ordering for values of type A.
When to use
Use when you need to define how values of a type are compared.
Details
An order returns -1 when the first value is less than the second, 0 when
the values are equal according to this ordering, and 1 when the first value
is greater than the second. It must satisfy total ordering laws: totality,
antisymmetry, and transitivity.
See
Signature
interface Order<in A> { (self: A, that: A): Ordering;}Example
(Defining a custom Order)
import { Order } from "effect"
const byAge: Order.Order<{ name: string; age: number }> = (self, that) => { if (self.age < that.age) return -1 if (self.age > that.age) return 1 return 0}
const person1 = { name: "Alice", age: 30 }const person2 = { name: "Bob", age: 25 }byAge(person1, person2) // => 1Other
Predicates
Checks whether a value is between a minimum and a maximum (inclusive) according to the given order.
When to use
Use when you need range checks that respect domain-specific ordering, such as dates, versions, or custom priorities, instead of JavaScript numeric comparison.
Details
Returns true when the value is greater than or equal to minimum and less
than or equal to maximum. Values outside the range return false. Both
bounds are inclusive.
See
- clamp to clamp a value to a range
- isLessThanOrEqualTo for less than or equal check
- isGreaterThanOrEqualTo for greater than or equal check
Signature
declare function isBetween<A>(O: Order<A>): { (options: { maximum: A; minimum: A; }): (self: A) => boolean; (self: A, options: { maximum: A; minimum: A; }): boolean;}Example
(Checking ranges)
import { Order } from "effect"
const betweenNumber = Order.isBetween(Order.Number)
betweenNumber(5, { minimum: 1, maximum: 10 }) // => truebetweenNumber(1, { minimum: 1, maximum: 10 }) // => truebetweenNumber(10, { minimum: 1, maximum: 10 }) // => truebetweenNumber(0, { minimum: 1, maximum: 10 }) // => falsebetweenNumber(11, { minimum: 1, maximum: 10 }) // => falseisGreaterThan
Checks whether one value is strictly greater than another according to the given order.
When to use
Use when you need a boolean greater-than predicate using an Order.
Details
Returns true if the order returns 1, meaning the first value is greater
than the second. Equal or lesser values return false.
See
- isGreaterThanOrEqualTo for non-strict greater than or equal
- isLessThan for strict less than
Signature
declare function isGreaterThan<A>(O: Order<A>): { (that: A): (self: A) => boolean; (self: A, that: A): boolean;}Example
(Checking greater-than comparisons)
import { Order } from "effect"
const isGreaterThanNumber = Order.isGreaterThan(Order.Number)
isGreaterThanNumber(2, 1) // => trueisGreaterThanNumber(1, 2) // => falseisGreaterThanNumber(1, 1) // => falseisGreaterThanOrEqualTo
Checks whether one value is greater than or equal to another according to the given order.
When to use
Use when you need a boolean greater-than-or-equal predicate using an
Order.
Details
Returns true if the order returns 1 or 0, and returns false only if
the order returns -1.
See
- isGreaterThan for strict greater than
- isLessThanOrEqualTo for less than or equal
Signature
declare function isGreaterThanOrEqualTo<A>(O: Order<A>): { (that: A): (self: A) => boolean; (self: A, that: A): boolean;}Example
(Checking greater-than-or-equal comparisons)
import { Order } from "effect"
const isGreaterThanOrEqualToNumber = Order.isGreaterThanOrEqualTo(Order.Number)
isGreaterThanOrEqualToNumber(2, 1) // => trueisGreaterThanOrEqualToNumber(1, 1) // => trueisGreaterThanOrEqualToNumber(1, 2) // => falseisLessThan
Checks whether one value is strictly less than another according to the given order.
When to use
Use when you need a boolean less-than predicate using an Order.
Details
Returns true if the order returns -1, meaning the first value is less
than the second. Equal or greater values return false.
See
- isLessThanOrEqualTo for non-strict less than or equal
- isGreaterThan for strict greater than
Signature
declare function isLessThan<A>(O: Order<A>): { (that: A): (self: A) => boolean; (self: A, that: A): boolean;}Example
(Checking less-than comparisons)
import { Order } from "effect"
const isLessThanNumber = Order.isLessThan(Order.Number)
isLessThanNumber(1, 2) // => trueisLessThanNumber(2, 1) // => falseisLessThanNumber(1, 1) // => falseisLessThanOrEqualTo
Checks whether one value is less than or equal to another according to the given order.
When to use
Use when you need a boolean less-than-or-equal predicate using an Order.
Details
Returns true if the order returns -1 or 0, and returns false only if
the order returns 1.
See
- isLessThan for strict less than
- isGreaterThan for strict greater than
Signature
declare function isLessThanOrEqualTo<A>(O: Order<A>): { (that: A): (self: A) => boolean; (self: A, that: A): boolean;}Example
(Checking less-than-or-equal comparisons)
import { Order } from "effect"
const isLessThanOrEqualToNumber = Order.isLessThanOrEqualTo(Order.Number)
isLessThanOrEqualToNumber(1, 2) // => trueisLessThanOrEqualToNumber(1, 1) // => trueisLessThanOrEqualToNumber(2, 1) // => falseUtility Types
OrderTypeLambda interface
Type lambda for the Order type class, used internally for higher-kinded type operations.
When to use
Use when you need to abstract over Order in higher-kinded type code.
Details
This is type-level only, has no runtime representation, and is used internally by the Effect type system.
Signature
interface OrderTypeLambda extends TypeLambda { readonly type: Order<unknown>;}