even more ideas with types and javascript (equality, ordering and enumeration)

more interesing stuff with types and javascript. let's see equality, ordering and enumeration.

every application has some types that doesn't have much behaviors. they mostly just represent something. for example: currencies.

the accepted currencies are: USD, BRL and JPY.

we could use an enum to make our lives easier.

enum Currency {
  USD = 'USD',
  BRL = 'BRL',
  JPY = 'JPY'
}

{
  "currency": Currency.JPY,
  "amount": 10
}

this is better than using raw strings all over the place to avoid typos and forgetting if a currency is valid.

these is no much we can do with them, they only help if we are doing equality.

object.currency === Currency.JPY

...and nothing more.

let's say we want to put them in order by currency. we would need to do it by hand and it's terrible.

equality

this is the easy one.

const USD = new (function USD() {});
const BRL = new (function BRL() {});
const JPY = new (function JPY() {});

this will allow us to attach behaviors to the objects.

USD === USD;
// true

USD === BRL;
// false

// if we want to follow fantasy land specification.

function currencyEq(b) {
  return this === b;
};

USD.equals = currencyEq;
BRL.equals = currencyEq;
JPY.equals = currencyEq;

USD.equals(JPY);
// false

USD.equals(USD);
// true

Still didn't change much, but we now have the hability to improve your simple types.

enumeration

we don't get really enumeration from our enum types, but now the can implement ourself!

USD.toEnum = () => 0;
BRL.toEnum = () => 1;
JPY.toEnum = () => 2;

const Currency = {
  fromEnum(x) {
    switch(x) {
    case 0: return USD;
    case 1: return BRL;
    case 2: return JPY;
    default: { throw new Error(`no current for ${x}.`); }
    }
  }
};

// nice properties!
Currency.fromEnum(currency.toEnum()) === currency;
// true

// now can do weird stuff...

function cycle(n, fn) {
  let x = 0;
  return () => fn(x++ % n);
}

const currenciesCycle = cycle(3, Currency.fromEnum);

currenciesCycle();
// USD
currenciesCycle();
// BRL
currenciesCycle();
// JPY
currenciesCycle();
// USD
currenciesCycle();
// BRL
currenciesCycle();
// JPY
...

ordering

ordering is also an interesting operation that people don't think about.

// in this example, we are going to
// use the inverse of enum.
// so, the order will be: USD, BRL, JPY
function currencyOrd(b) {
  return this.toEnum() > b.toEnum();
}

USD.lte = currencyOrd;
BRL.lte = currencyOrd;
JPY.lte = currencyOrd;

const Currency = {
  // ...
  sortAsc(a, b) {
    return -b.lte(a);
  },
  sortDesc(a, b) {
    return -a.lte(b);
  }
};

// sorting descendent
[JPY, USD, BRL, JPY, BRL].sort(Currency.sortDesc);
// [JPY, JPY, BRL, BRL, USD]

// sorting ascendent
[JPY, USD, BRL, JPY, BRL].sort(Currency.sortAsc);
// [USD, BRL, BRL, JPY, JPY]

the complete example can be found at diasbruno/equality-enum-order-with-javascript at github.