We need an equality function
Nobody has claimed this yet.
- Dominant language
- HTML
- Stars
- 58
- Forks
- 12
- Avg merge
- 2h 35m
- Merged PRs (30d)
- 2
Description
With the recent changes in #118 allowing .value to hold an Array, we have inadvertently created a silent trap for developers who wish to compare two Amounts for equality.
The Problem
Previously, developers could rely on amt1.unit === amt2.unit && amt1.value === amt2.value. This worked fine when value was always a primitive. However, when it is an array, this naive check will fail for sequence units since [1, 2] !== [1, 2].
The problem is that developers will still try to do this, since it works 90% of the time: most Amounts are not sequence units, and most Amounts hold Number values. This is the worst kind of footgun for the language to let slip: code that looks correct and works most of the time but fails on cases that might not have shown up in testing.
In Temporal, I've already seen code that gets the epochNanoseconds to do addition and comparison, but we have a good solution: use the methods. We need a similarly elegant paved path to solve user needs when they try to compare Amounts.
Why We Need Equality
Some delegates have asked the question: Why do we need to be able to test for equality?
While keeping the API surface small is a crucial goal, Amounts represent state, and comparing stateful objects for equality is a fundamental operation in coding. Example use cases for comparing Amounts that come from different sources:
- In data structures (for example, deduplicating entries in a database)
- In application behavior (for example, turning a temperature slider green when it equals the target temperature)
- In updating state in a view model (for example, checking whether we need to send a PUT operation to a server if a user changes their weight, or knowing when to trigger a re-render of a UI)
If we don't provide an ergonomic equality operation, we are just forcing developers to write, maintain, and inevitably misconfigure their own complex deep-equality helper for these everyday use cases.
The Solution
I therefore think we need to work on designing Amount.prototype.equals.
There are a number of important design questions with this function, but nothing insurmountable. Two key questions are:
- Do we convert numeric types before comparing? (example:
1vs1n) - Do we convert to the same unit before comparing? (example:
1 kmvs1000 m)
My answer to both is: let's pick a predictable default, and add options to .equals() to allow the developer to tune that behavior. My initial instinct is that the default should probably be "strict deep equality" (=== on primitive fields and elements of the array).
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reviewing the current Amount API, especially .value and the changes introduced in #118, then examine how Amount.prototype.equals should address the two stated design questions. Done means the equality behavior and any conversion options are agreed and documented well enough to implement and test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript
- Domain
- api
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100