Effect CommunityEC
Effect Community11mo ago
1 reply
sproott

Disallow mixing of branded types

I have two branded Decimal types for working with money, WithoutVat and WithVat. I want to keep them distinct from each other and do some limited arithmetic that preserves their types.

When encoded as branded types, I can call regular Decimal methods on them, but the return type is Decimal, requiring a manual typecast after each operation, and in case of binary operations, the other parameter can be any Decimal, allowing the mixing of WithoutVat and WithVat values.

Since I need a very similar API for both types, I've tried creating a common base class like so:

export class Price {
  #value: Decimal

  constructor(value: Decimal) {
    this.#value = value
  }

  get value() {
    return this.#value
  }

  plus(other: Price) {
    return new Price(this.#value.plus(other.value))
  }

  minus(other: Price) {
    return new Price(this.#value.minus(other.value))
  }
}


But now I'm not sure how to derive the two distinct types from that. I thought of extending from the Price class, but then I'd somehow need to reference the subtype within the Price methods, for their parameters and return values.

Is there some better way of achieving the end goal I've described?
Was this page helpful?