stdtraits~ Equals


Trait to check whether two val­ues are equal.

const { Equals, equals, eq, uneq, as­ser­tEquals, as­ser­tUneq } = re­quire('fer­rum');

// Im­ple­ment­ing this type
class Bar {
  con­structor(foo, bang) {
    this.foo = foo;
    this.bang = bang;

  [Equals.sym](otr) {
    re­turn otr in­stanceof Bar
        && eq(this.foo, otr.foo)
        && eq(this.bang, otr.bang);

// Or al­tern­at­ively
//Equals.impl(Bar, (a, b) => {
//  ...

// Test for equal­ity, nor­mally you would use eq() and uneq()
as­ser­tEquals(new Bar(42, 23), new Bar(42, 23));
as­ser­tUneq(new Bar(42, 23), new Bar(0, 0));

Nor­mally this trait should not be used dir­ectly; con­sider us­ing eq() in­stead.

This trait should be used only in cases where ===/is() is too strict. Equals is for cases in which the con­tent of two vari­ables or data struc­tures is the same/​se­mantic­ally equi­val­ent.


(value1: Any, value2: Any) => r: Boolean


  • Equals.in­voke(a, b) <=> Equals.in­voke(b, a)

This law seems trivial at first, but one ac­tu­ally needs to take some care to make this work: The trait re­solves to the im­ple­ment­a­tion for the first ar­gu­ment! So Equals.in­voke(a: Num­ber, b: String) and Equals.in­voke(a: String, b: Num­ber) will ac­tu­ally re­solve to two dif­fer­ent im­ple­ment­a­tions. The easi­est way to make this work is just to add a check (a, b) => type(b) === Num­ber to the im­ple­ment­a­tion for num­ber and adding an equi­val­ent check in string. If com­par­ing across types is ac­tu­ally de­sired (and might re­turn true), I sug­gest us­ing the same code for both im­ple­ment­a­tions: Con­sider the fol­low­ing con­trive ex­amples:

const { Equals, type } = re­quire('fer­rum');

Equals.impl(Num­ber, (a, b) =>
  (type(b) === String || type(b) === Num­ber)
  && a.to­String() === b.to­String());
Equals.impl(String, (a, b) =>
  (type(b) === String || type(b) === Num­ber)
  && a.to­String() === b.to­String());

Spe­cial­iz­a­tion notes

Ex­tra im­ple­ment­a­tions provided for Date, Reg­Exp, URL and typed ar­rays.

Note that for sets: eq(new Set([{}]), new Set([{}])) does not hold true, since in sets keys and val­ues are the same thing and keys al­ways fol­low === se­mantics.

See: eq See: uneq See: as­ser­tEquals See: as­ser­tUneq