atomic-fns 1.1.7 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. package/README.md +405 -60
  2. package/dist/array/index.d.ts +9 -0
  3. package/dist/array/index.js +9 -0
  4. package/dist/array/list.d.ts +99 -0
  5. package/dist/array/list.js +133 -0
  6. package/dist/array/sets.d.ts +130 -0
  7. package/dist/array/sets.js +213 -0
  8. package/dist/async/index.d.ts +6 -0
  9. package/dist/async/index.js +6 -0
  10. package/dist/async/retry.d.ts +38 -0
  11. package/dist/async/retry.js +56 -0
  12. package/dist/async/sleep.d.ts +42 -0
  13. package/dist/async/sleep.js +76 -0
  14. package/dist/collections/bisect.d.ts +103 -0
  15. package/dist/collections/bisect.js +157 -0
  16. package/dist/collections/deque.d.ts +67 -97
  17. package/dist/collections/deque.js +197 -249
  18. package/dist/collections/entries.d.ts +89 -0
  19. package/dist/collections/entries.js +131 -0
  20. package/dist/collections/frozen-set.d.ts +42 -0
  21. package/dist/collections/frozen-set.js +64 -0
  22. package/dist/collections/group.d.ts +141 -0
  23. package/dist/collections/group.js +241 -0
  24. package/dist/collections/heap.d.ts +64 -0
  25. package/dist/collections/heap.js +205 -0
  26. package/dist/collections/index.d.ts +15 -642
  27. package/dist/collections/index.js +14 -716
  28. package/dist/collections/internal/arrayKeys.d.ts +19 -0
  29. package/dist/collections/internal/arrayKeys.js +83 -0
  30. package/dist/collections/internal/invariants.d.ts +4 -0
  31. package/dist/collections/internal/invariants.js +12 -0
  32. package/dist/collections/internal/iterable.d.ts +25 -0
  33. package/dist/collections/internal/iterable.js +62 -0
  34. package/dist/collections/iterate.d.ts +162 -0
  35. package/dist/collections/iterate.js +188 -0
  36. package/dist/collections/lru-cache.d.ts +58 -0
  37. package/dist/collections/lru-cache.js +164 -0
  38. package/dist/collections/order.d.ts +19 -0
  39. package/dist/collections/order.js +38 -0
  40. package/dist/collections/shape.d.ts +32 -0
  41. package/dist/collections/shape.js +86 -0
  42. package/dist/collections/sorted-map.d.ts +171 -0
  43. package/dist/collections/sorted-map.js +845 -0
  44. package/dist/collections/sorted-set.d.ts +103 -0
  45. package/dist/collections/sorted-set.js +147 -0
  46. package/dist/collections/splay-tree.d.ts +82 -0
  47. package/dist/collections/splay-tree.js +354 -0
  48. package/dist/collections/trie.d.ts +58 -0
  49. package/dist/collections/trie.js +196 -0
  50. package/dist/decimal/currency.d.ts +211 -0
  51. package/dist/decimal/currency.js +321 -0
  52. package/dist/decimal/decimal.d.ts +299 -0
  53. package/dist/decimal/decimal.js +660 -0
  54. package/dist/decimal/index.d.ts +11 -145
  55. package/dist/decimal/index.js +10 -374
  56. package/dist/decimal/internal/bits.d.ts +2 -0
  57. package/dist/decimal/internal/bits.js +7 -0
  58. package/dist/decimal/internal/echo.d.ts +4 -0
  59. package/dist/decimal/internal/echo.js +6 -0
  60. package/dist/decimal/internal/isqrt.d.ts +9 -0
  61. package/dist/decimal/internal/isqrt.js +34 -0
  62. package/dist/decimal/internal/locale.d.ts +7 -0
  63. package/dist/decimal/internal/locale.js +24 -0
  64. package/dist/decimal/internal/minor-units.d.ts +2 -0
  65. package/dist/decimal/internal/minor-units.js +33 -0
  66. package/dist/decimal/internal/pow10.d.ts +24 -0
  67. package/dist/decimal/internal/pow10.js +96 -0
  68. package/dist/encoding/base64.d.ts +39 -0
  69. package/dist/encoding/base64.js +53 -0
  70. package/dist/encoding/hex.d.ts +23 -0
  71. package/dist/encoding/hex.js +34 -0
  72. package/dist/encoding/index.d.ts +6 -0
  73. package/dist/encoding/index.js +6 -0
  74. package/dist/function/debounce.d.ts +68 -0
  75. package/dist/function/debounce.js +203 -0
  76. package/dist/function/index.d.ts +6 -0
  77. package/dist/function/index.js +6 -0
  78. package/dist/function/shared.d.ts +2 -0
  79. package/dist/function/shared.js +5 -0
  80. package/dist/function/wrap.d.ts +130 -0
  81. package/dist/function/wrap.js +113 -0
  82. package/dist/hash/digest.d.ts +18 -0
  83. package/dist/hash/digest.js +26 -0
  84. package/dist/hash/hash.d.ts +22 -0
  85. package/dist/hash/hash.js +252 -0
  86. package/dist/hash/hashString.d.ts +13 -0
  87. package/dist/hash/hashString.js +53 -0
  88. package/dist/hash/index.d.ts +8 -0
  89. package/dist/hash/index.js +8 -0
  90. package/dist/hash/stableStringify.d.ts +19 -0
  91. package/dist/hash/stableStringify.js +102 -0
  92. package/dist/id/index.d.ts +7 -0
  93. package/dist/id/index.js +7 -0
  94. package/dist/id/nanoid.d.ts +16 -0
  95. package/dist/id/nanoid.js +65 -0
  96. package/dist/id/uniqueId.d.ts +14 -0
  97. package/dist/id/uniqueId.js +20 -0
  98. package/dist/id/uuid.d.ts +25 -0
  99. package/dist/id/uuid.js +64 -0
  100. package/dist/index.d.ts +15 -8
  101. package/dist/index.js +15 -8
  102. package/dist/internal/bytes.d.ts +11 -0
  103. package/dist/internal/bytes.js +33 -0
  104. package/dist/internal/codec.d.ts +11 -0
  105. package/dist/internal/codec.js +84 -0
  106. package/dist/internal/compare.d.ts +10 -0
  107. package/dist/internal/compare.js +26 -0
  108. package/dist/internal/crypto.d.ts +5 -0
  109. package/dist/internal/crypto.js +11 -0
  110. package/dist/internal/keys.d.ts +12 -0
  111. package/dist/internal/keys.js +23 -0
  112. package/dist/internal/kind.d.ts +44 -0
  113. package/dist/internal/kind.js +139 -0
  114. package/dist/internal/sparse.d.ts +51 -0
  115. package/dist/internal/sparse.js +104 -0
  116. package/dist/internal/text.d.ts +7 -0
  117. package/dist/internal/text.js +15 -0
  118. package/dist/internal/timer.d.ts +10 -0
  119. package/dist/internal/timer.js +17 -0
  120. package/dist/internal/truncate.d.ts +10 -0
  121. package/dist/internal/truncate.js +22 -0
  122. package/dist/internal/walk.d.ts +47 -0
  123. package/dist/internal/walk.js +100 -0
  124. package/dist/is/index.d.ts +8 -0
  125. package/dist/is/index.js +8 -0
  126. package/dist/is/isArrayLike.d.ts +18 -0
  127. package/dist/is/isArrayLike.js +25 -0
  128. package/dist/is/isError.d.ts +13 -0
  129. package/dist/is/isError.js +18 -0
  130. package/dist/is/isNil.d.ts +12 -0
  131. package/dist/is/isNil.js +14 -0
  132. package/dist/is/isPlainObject.d.ts +15 -0
  133. package/dist/is/isPlainObject.js +34 -0
  134. package/dist/number/index.d.ts +7 -0
  135. package/dist/number/index.js +7 -0
  136. package/dist/number/round.d.ts +86 -0
  137. package/dist/number/round.js +130 -0
  138. package/dist/number/stats.d.ts +52 -0
  139. package/dist/number/stats.js +115 -0
  140. package/dist/object/cloneDeep.d.ts +28 -0
  141. package/dist/object/cloneDeep.js +200 -0
  142. package/dist/object/index.d.ts +14 -0
  143. package/dist/object/index.js +13 -0
  144. package/dist/object/isEqual.d.ts +64 -0
  145. package/dist/object/isEqual.js +289 -0
  146. package/dist/object/matches.d.ts +40 -0
  147. package/dist/object/matches.js +284 -0
  148. package/dist/object/merge.d.ts +66 -0
  149. package/dist/object/merge.js +272 -0
  150. package/dist/object/parsePath.d.ts +22 -0
  151. package/dist/object/parsePath.js +111 -0
  152. package/dist/object/path.d.ts +85 -0
  153. package/dist/object/path.js +208 -0
  154. package/dist/object/pick.d.ts +91 -0
  155. package/dist/object/pick.js +180 -0
  156. package/dist/object/reshape.d.ts +73 -0
  157. package/dist/object/reshape.js +144 -0
  158. package/dist/random/index.d.ts +96 -32
  159. package/dist/random/index.js +215 -50
  160. package/dist/string/case.d.ts +71 -0
  161. package/dist/string/case.js +152 -0
  162. package/dist/string/fold.d.ts +35 -0
  163. package/dist/string/fold.js +100 -0
  164. package/dist/string/index.d.ts +6 -187
  165. package/dist/string/index.js +6 -226
  166. package/dist/string/truncate.d.ts +25 -0
  167. package/dist/string/truncate.js +44 -0
  168. package/dist/string/words.d.ts +27 -0
  169. package/dist/string/words.js +241 -0
  170. package/package.json +101 -58
  171. package/dist/collections/BTree.d.ts +0 -229
  172. package/dist/collections/BTree.js +0 -1165
  173. package/dist/collections/Heap.d.ts +0 -69
  174. package/dist/collections/Heap.js +0 -181
  175. package/dist/collections/LRUCache.d.ts +0 -80
  176. package/dist/collections/LRUCache.js +0 -126
  177. package/dist/collections/SortedMap.d.ts +0 -92
  178. package/dist/collections/SortedMap.js +0 -131
  179. package/dist/collections/SortedSet.d.ts +0 -69
  180. package/dist/collections/SortedSet.js +0 -99
  181. package/dist/collections/SortedTree.d.ts +0 -103
  182. package/dist/collections/SortedTree.js +0 -141
  183. package/dist/collections/SplayTree.d.ts +0 -105
  184. package/dist/collections/SplayTree.js +0 -338
  185. package/dist/collections/Trie.d.ts +0 -42
  186. package/dist/collections/Trie.js +0 -104
  187. package/dist/collections/abc.d.ts +0 -152
  188. package/dist/collections/abc.js +0 -39
  189. package/dist/collections/frozenset.d.ts +0 -19
  190. package/dist/collections/frozenset.js +0 -30
  191. package/dist/functools/index.d.ts +0 -130
  192. package/dist/functools/index.js +0 -235
  193. package/dist/globals/index.d.ts +0 -285
  194. package/dist/globals/index.js +0 -463
  195. package/dist/i18n/currency.d.ts +0 -24
  196. package/dist/i18n/currency.js +0 -85
  197. package/dist/i18n/date/index.d.ts +0 -203
  198. package/dist/i18n/date/index.js +0 -531
  199. package/dist/i18n/date/utils.d.ts +0 -65
  200. package/dist/i18n/date/utils.js +0 -290
  201. package/dist/i18n/duration.d.ts +0 -112
  202. package/dist/i18n/duration.js +0 -392
  203. package/dist/i18n/format.d.ts +0 -31
  204. package/dist/i18n/format.js +0 -506
  205. package/dist/i18n/index.d.ts +0 -8
  206. package/dist/i18n/index.js +0 -8
  207. package/dist/itertools/index.d.ts +0 -255
  208. package/dist/itertools/index.js +0 -437
  209. package/dist/math/index.d.ts +0 -96
  210. package/dist/math/index.js +0 -98
  211. package/dist/mod.d.ts +0 -1
  212. package/dist/mod.js +0 -1
  213. package/dist/operators/index.d.ts +0 -152
  214. package/dist/operators/index.js +0 -305
  215. package/dist/types.d.ts +0 -19
  216. package/dist/types.js +0 -1
@@ -0,0 +1,321 @@
1
+ var _a;
2
+ import { Decimal } from './decimal.js';
3
+ import { quoteForError } from './internal/echo.js';
4
+ import { isoMinorUnits } from './internal/minor-units.js';
5
+ /** Fraction digits {@link Currency.format} shows by default, so an exact amount keeps its digits. */
6
+ const EXACT_FRACTION_DIGITS = 20;
7
+ const CURRENCY_CODE = /^[A-Za-z]{3}$/;
8
+ function minorUnitDigits(code) {
9
+ const digits = isoMinorUnits(code);
10
+ if (digits === undefined) {
11
+ throw new RangeError(`${code} has no ISO 4217 minor unit; pass the digits to round()`);
12
+ }
13
+ return digits;
14
+ }
15
+ /** True unless `options` already say how many digits to show. */
16
+ function showsExactDigits(options) {
17
+ return (options.maximumFractionDigits === undefined &&
18
+ options.minimumSignificantDigits === undefined &&
19
+ options.maximumSignificantDigits === undefined &&
20
+ (options.roundingIncrement ?? 1) === 1 &&
21
+ (options.notation ?? 'standard') === 'standard');
22
+ }
23
+ function assertCurrency(value) {
24
+ if (!(value instanceof Currency))
25
+ throw new TypeError('expected a Currency');
26
+ }
27
+ /**
28
+ * An exact amount of money in one ISO 4217 currency, as the TC39 Amount proposal pairs a value
29
+ * with its unit. Arithmetic and ordering with another currency throw `RangeError`; nothing
30
+ * converts between currencies.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * const price = new Currency('19.99', 'USD')
35
+ * price.multiply(3).format('en-US') // '$59.97'
36
+ * price.add(new Currency('0.01', 'USD')).toString() // '20 USD'
37
+ * ```
38
+ */
39
+ export class Currency {
40
+ /**
41
+ * Orders two amounts of the same currency, for `toSorted` and sorted collections.
42
+ * @throws {TypeError} when `a` or `b` is not a Currency.
43
+ * @throws {RangeError} when the currencies differ.
44
+ * @example
45
+ * ```ts
46
+ * [new Currency(5, 'EUR'), new Currency(2, 'EUR')].toSorted(Currency.compare).map(String)
47
+ * // ['2 EUR', '5 EUR']
48
+ * ```
49
+ */
50
+ static compare(a, b) {
51
+ assertCurrency(a);
52
+ return a.compare(b);
53
+ }
54
+ #amount;
55
+ #currency;
56
+ /**
57
+ * Pairs an amount with a currency code.
58
+ * @param amount The amount, read as {@link Decimal} reads it.
59
+ * @param currency A three-letter ISO 4217 code, in any case.
60
+ * @throws {TypeError} when `currency` is not a string, or `amount` not a Decimal input.
61
+ * @throws {RangeError} when `currency` is not three letters, or `amount` is malformed.
62
+ * @example
63
+ * ```ts
64
+ * new Currency('12.50', 'usd').currency // 'USD'
65
+ * ```
66
+ */
67
+ constructor(amount, currency) {
68
+ if (typeof currency !== 'string')
69
+ throw new TypeError('currency must be a string');
70
+ if (!CURRENCY_CODE.test(currency)) {
71
+ throw new RangeError(`currency must be a three-letter ISO 4217 code, not ${quoteForError(currency)}`);
72
+ }
73
+ this.#amount = amount instanceof Decimal ? amount : new Decimal(amount);
74
+ this.#currency = currency.toUpperCase();
75
+ }
76
+ /** The exact amount. */
77
+ get amount() {
78
+ return this.#amount;
79
+ }
80
+ /** The upper-case ISO 4217 code, such as `'USD'`. */
81
+ get currency() {
82
+ return this.#currency;
83
+ }
84
+ #with(amount) {
85
+ return new _a(amount, this.#currency);
86
+ }
87
+ #amountOf(other) {
88
+ assertCurrency(other);
89
+ if (other.#currency !== this.#currency) {
90
+ throw new RangeError(`currency mismatch: ${this.#currency} and ${other.#currency}`);
91
+ }
92
+ return other.#amount;
93
+ }
94
+ /**
95
+ * The sum of two amounts of the same currency.
96
+ * @throws {TypeError} when `other` is not a Currency.
97
+ * @throws {RangeError} when the currencies differ.
98
+ * @example
99
+ * ```ts
100
+ * new Currency('0.1', 'USD').add(new Currency('0.2', 'USD')).toString() // '0.3 USD'
101
+ * ```
102
+ */
103
+ add(other) {
104
+ return this.#with(this.#amount.add(this.#amountOf(other)));
105
+ }
106
+ /**
107
+ * The difference of two amounts of the same currency.
108
+ * @throws {TypeError} when `other` is not a Currency.
109
+ * @throws {RangeError} when the currencies differ.
110
+ * @example
111
+ * ```ts
112
+ * new Currency(10, 'EUR').subtract(new Currency('2.5', 'EUR')).toString() // '7.5 EUR'
113
+ * ```
114
+ */
115
+ subtract(other) {
116
+ return this.#with(this.#amount.subtract(this.#amountOf(other)));
117
+ }
118
+ /**
119
+ * This amount times a plain factor.
120
+ * @example
121
+ * ```ts
122
+ * new Currency('19.99', 'USD').multiply(3).toString() // '59.97 USD'
123
+ * ```
124
+ */
125
+ multiply(factor) {
126
+ return this.#with(this.#amount.multiply(factor));
127
+ }
128
+ /**
129
+ * This amount divided by a plain divisor, rounded as {@link Decimal.divide} rounds, to 34
130
+ * significant digits by default; follow with {@link Currency.round} for the minor unit.
131
+ * @throws {RangeError} for a zero divisor.
132
+ * @example
133
+ * ```ts
134
+ * new Currency(10, 'USD').divide(3).round().toString() // '3.33 USD'
135
+ * ```
136
+ */
137
+ divide(divisor, options) {
138
+ return this.#with(this.#amount.divide(divisor, options));
139
+ }
140
+ /**
141
+ * This amount with the opposite sign.
142
+ * @example
143
+ * ```ts
144
+ * new Currency(5, 'USD').negate().toString() // '-5 USD'
145
+ * ```
146
+ */
147
+ negate() {
148
+ return this.#with(this.#amount.negate());
149
+ }
150
+ /**
151
+ * The absolute amount.
152
+ * @example
153
+ * ```ts
154
+ * new Currency(-5, 'USD').abs().toString() // '5 USD'
155
+ * ```
156
+ */
157
+ abs() {
158
+ return this.#with(this.#amount.abs());
159
+ }
160
+ /**
161
+ * Rounds the amount, by default to the currency's ISO 4217 minor unit (2 digits for USD, 0 for
162
+ * JPY, 3 for IQD). The mode defaults to `'halfEven'`, while {@link Currency.format} rounds what
163
+ * it shows half away from zero, as `Intl.NumberFormat` does.
164
+ * @param digits Fractional digits (may be negative); defaults to the minor unit.
165
+ * @param roundingMode One of the `Intl.NumberFormat` rounding modes; defaults to `'halfEven'`.
166
+ * @throws {RangeError} when `digits` is left out and ISO 4217 gives the code no minor unit, as
167
+ * for XAU or a code it does not list.
168
+ * @example
169
+ * ```ts
170
+ * new Currency('2.675', 'USD').round().toString() // '2.68 USD'
171
+ * new Currency('1234.5', 'JPY').round().toString() // '1234 JPY'
172
+ * new Currency('2.665', 'USD').round(undefined, 'halfExpand').toString() // '2.67 USD'
173
+ * ```
174
+ */
175
+ round(digits = minorUnitDigits(this.#currency), roundingMode) {
176
+ return this.#with(this.#amount.round(digits, roundingMode));
177
+ }
178
+ /**
179
+ * Orders this amount against another of the same currency: -1, 0 or 1.
180
+ * @throws {TypeError} when `other` is not a Currency.
181
+ * @throws {RangeError} when the currencies differ.
182
+ * @example
183
+ * ```ts
184
+ * new Currency(1, 'USD').compare(new Currency('1.00', 'USD')) // 0
185
+ * ```
186
+ */
187
+ compare(other) {
188
+ return this.#amount.compare(this.#amountOf(other));
189
+ }
190
+ /**
191
+ * True for a Currency with the same code and amount; false for anything else, including the
192
+ * same amount in another currency.
193
+ * @example
194
+ * ```ts
195
+ * new Currency(1, 'USD').equals(new Currency(1, 'EUR')) // false
196
+ * ```
197
+ */
198
+ equals(other) {
199
+ return (other instanceof _a &&
200
+ other.#currency === this.#currency &&
201
+ this.#amount.equals(other.#amount));
202
+ }
203
+ /**
204
+ * True when this amount is less than `other`.
205
+ * @throws {TypeError} when `other` is not a Currency.
206
+ * @throws {RangeError} when the currencies differ.
207
+ * @example
208
+ * ```ts
209
+ * new Currency(1, 'USD').lessThan(new Currency(2, 'USD')) // true
210
+ * ```
211
+ */
212
+ lessThan(other) {
213
+ return this.compare(other) < 0;
214
+ }
215
+ /**
216
+ * True when this amount is less than or equal to `other`.
217
+ * @throws {TypeError} when `other` is not a Currency.
218
+ * @throws {RangeError} when the currencies differ.
219
+ * @example
220
+ * ```ts
221
+ * new Currency(2, 'USD').lessThanOrEqual(new Currency(2, 'USD')) // true
222
+ * ```
223
+ */
224
+ lessThanOrEqual(other) {
225
+ return this.compare(other) <= 0;
226
+ }
227
+ /**
228
+ * True when this amount is greater than `other`.
229
+ * @throws {TypeError} when `other` is not a Currency.
230
+ * @throws {RangeError} when the currencies differ.
231
+ * @example
232
+ * ```ts
233
+ * new Currency(3, 'USD').greaterThan(new Currency(2, 'USD')) // true
234
+ * ```
235
+ */
236
+ greaterThan(other) {
237
+ return this.compare(other) > 0;
238
+ }
239
+ /**
240
+ * True when this amount is greater than or equal to `other`.
241
+ * @throws {TypeError} when `other` is not a Currency.
242
+ * @throws {RangeError} when the currencies differ.
243
+ * @example
244
+ * ```ts
245
+ * new Currency(2, 'USD').greaterThanOrEqual(new Currency(3, 'USD')) // false
246
+ * ```
247
+ */
248
+ greaterThanOrEqual(other) {
249
+ return this.compare(other) >= 0;
250
+ }
251
+ /**
252
+ * Formats with `Intl.NumberFormat` in currency style. Unless `options` set the digits, the
253
+ * amount keeps its own fraction digits, up to 20, instead of rounding to the minor unit, so
254
+ * `0.125` dollars show as `$0.125`; pass `{ maximumFractionDigits: 2 }` or {@link Currency.round}
255
+ * first for minor units. A `roundingMode` alone changes nothing, since no digits are cut; pair it
256
+ * with `maximumFractionDigits`. `style` and `currency` always come from this amount.
257
+ * @throws {RangeError} when the amount is beyond `Number.MAX_VALUE`, which `Intl` shows as `∞`,
258
+ * or the locale is malformed or longer than 255 characters.
259
+ * @example
260
+ * ```ts
261
+ * new Currency('1234.5', 'EUR').format('de-DE') // '1.234,50 €'
262
+ * new Currency('0.125', 'USD').format('en-US', { maximumFractionDigits: 2 }) // '$0.13'
263
+ * ```
264
+ */
265
+ format(locale, options = {}) {
266
+ const merged = {
267
+ ...options,
268
+ style: 'currency',
269
+ currency: this.#currency
270
+ };
271
+ if (showsExactDigits(merged)) {
272
+ merged.maximumFractionDigits = Math.max(EXACT_FRACTION_DIGITS, merged.minimumFractionDigits ?? 0);
273
+ }
274
+ return this.#amount.toLocaleString(locale, merged);
275
+ }
276
+ /**
277
+ * The same as {@link Currency.format}, under the name `Intl` and Temporal use.
278
+ * @example
279
+ * ```ts
280
+ * new Currency(5, 'GBP').toLocaleString('en-GB') // '£5.00'
281
+ * ```
282
+ */
283
+ toLocaleString(locales, options) {
284
+ return this.format(locales, options);
285
+ }
286
+ /**
287
+ * The amount's canonical string and the code, such as `'12.5 USD'`, for logs and keys.
288
+ * @example
289
+ * ```ts
290
+ * new Currency('12.50', 'usd').toString() // '12.5 USD'
291
+ * ```
292
+ */
293
+ toString() {
294
+ return `${this.#amount.toString()} ${this.#currency}`;
295
+ }
296
+ /** The same string as {@link Currency.toString}, so `JSON.stringify` keeps every digit. */
297
+ toJSON() {
298
+ return this.toString();
299
+ }
300
+ /**
301
+ * What `console.log` and `util.inspect` show, such as `Currency { 12.5 USD }`. The symbol is
302
+ * the runtime's own inspection hook, read by Node and runtimes compatible with it, not a
303
+ * protocol of this package.
304
+ * @example
305
+ * ```ts
306
+ * console.log(new Currency('12.50', 'USD')) // Currency { 12.5 USD }
307
+ * ```
308
+ */
309
+ [Symbol.for('nodejs.util.inspect.custom')]() {
310
+ return `Currency { ${this.toString()} }`;
311
+ }
312
+ /**
313
+ * Throws, so `<` and `+` cannot silently compare or add amounts. Use {@link Currency.compare}
314
+ * or {@link Currency.add}.
315
+ * @throws {TypeError} always.
316
+ */
317
+ valueOf() {
318
+ throw new TypeError('Currency cannot be converted to a primitive implicitly; use compare(), add() or format()');
319
+ }
320
+ }
321
+ _a = Currency;
@@ -0,0 +1,299 @@
1
+ /**
2
+ * How {@link Decimal.divide}, {@link Decimal.round}, {@link Decimal.sqrt} and
3
+ * {@link Decimal.toFixed} round, with the names `Intl.NumberFormat` uses:
4
+ * - `ceil`: toward +Infinity.
5
+ * - `floor`: toward -Infinity.
6
+ * - `expand`: away from zero.
7
+ * - `trunc`: toward zero.
8
+ * - `halfCeil`: nearest, ties toward +Infinity (as `Math.round`).
9
+ * - `halfFloor`: nearest, ties toward -Infinity.
10
+ * - `halfExpand`: nearest, ties away from zero (as `Number.prototype.toFixed`).
11
+ * - `halfTrunc`: nearest, ties toward zero.
12
+ * - `halfEven`: nearest, ties to the even neighbor (the default).
13
+ */
14
+ export type RoundingMode = 'ceil' | 'floor' | 'expand' | 'trunc' | 'halfCeil' | 'halfFloor' | 'halfExpand' | 'halfTrunc' | 'halfEven';
15
+ /** Options for {@link Decimal.divide} and {@link Decimal.sqrt}. */
16
+ export interface DivideOptions {
17
+ /**
18
+ * Significant digits of the result, from 1 to `Decimal.MAX_DIGITS` (default 34, as the TC39
19
+ * draft's 128-bit decimals carry). It counts significant digits, not fractional ones.
20
+ */
21
+ precision?: number;
22
+ /** How the last digit rounds (default `'halfEven'`). */
23
+ roundingMode?: RoundingMode;
24
+ }
25
+ /**
26
+ * A value {@link Decimal} reads: a Decimal, a decimal string, a bigint or a finite number.
27
+ * @example
28
+ * ```ts
29
+ * const inputs: DecimalInput[] = [new Decimal('1.5'), '2.5', 3n, 4.5]
30
+ * inputs.map((value) => new Decimal(value).toString()) // ['1.5', '2.5', '3', '4.5']
31
+ * ```
32
+ */
33
+ export type DecimalInput = Decimal | string | bigint | number;
34
+ /**
35
+ * An exact decimal number, shaped after the TC39 Decimal proposal: immutable, with arithmetic
36
+ * methods instead of operators. Values carry up to {@link Decimal.MAX_DIGITS} significant digits
37
+ * and an exponent within {@link Decimal.MAX_EXPONENT}; a result past either throws `RangeError`.
38
+ * Each operation costs time that grows with the digits of its operands, so size-limit untrusted
39
+ * lists before summing them.
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * const total = new Decimal('0.1').add('0.2')
44
+ * total.toString() // '0.3'
45
+ * total.equals('0.3') // true
46
+ * ```
47
+ */
48
+ export declare class Decimal {
49
+ #private;
50
+ /** Significant digits a Decimal holds; longer inputs and results throw `RangeError`. */
51
+ static get MAX_DIGITS(): number;
52
+ /** Largest absolute exponent a Decimal stores; larger values throw `RangeError`. */
53
+ static get MAX_EXPONENT(): number;
54
+ /** Largest fractional `digits` {@link Decimal.round} and {@link Decimal.toFixed} take. */
55
+ static get MAX_PRECISION(): number;
56
+ /**
57
+ * Orders two values, for `toSorted` and sorted collections.
58
+ * @example
59
+ * ```ts
60
+ * ['10', '9', '9.5'].map((s) => new Decimal(s)).toSorted(Decimal.compare).map(String)
61
+ * // ['9', '9.5', '10']
62
+ * ```
63
+ */
64
+ static compare(a: DecimalInput, b: DecimalInput): -1 | 0 | 1;
65
+ /**
66
+ * Reads a Decimal, a decimal string (`'-1.5'`, `'.5'`, `'2e-3'`, surrounding spaces allowed),
67
+ * a bigint, or a finite number through its shortest round-trip string, so `new Decimal(0.1)`
68
+ * is exactly `0.1`.
69
+ * @throws {TypeError} for any other type.
70
+ * @throws {RangeError} for a malformed string, a non-finite number, or a value past the bounds.
71
+ * @example
72
+ * ```ts
73
+ * new Decimal('1.50').toString() // '1.5'
74
+ * new Decimal(2n ** 64n).toString() // '18446744073709551616'
75
+ * ```
76
+ */
77
+ constructor(value: DecimalInput);
78
+ /**
79
+ * The exact sum.
80
+ * @example
81
+ * ```ts
82
+ * new Decimal('0.1').add('0.2').toString() // '0.3'
83
+ * ```
84
+ */
85
+ add(other: DecimalInput): Decimal;
86
+ /**
87
+ * The exact difference.
88
+ * @example
89
+ * ```ts
90
+ * new Decimal('1').subtract('0.9').toString() // '0.1'
91
+ * ```
92
+ */
93
+ subtract(other: DecimalInput): Decimal;
94
+ /**
95
+ * The exact product.
96
+ * @example
97
+ * ```ts
98
+ * new Decimal('1.5').multiply('-2').toString() // '-3'
99
+ * ```
100
+ */
101
+ multiply(other: DecimalInput): Decimal;
102
+ /**
103
+ * The quotient rounded to `precision` significant digits (default 34), as the TC39 draft
104
+ * rounds, so `new Decimal('1e-30').divide(3)` keeps its scale. An exact quotient with fewer
105
+ * digits is returned whole.
106
+ * @throws {TypeError} for `options` that is not an object.
107
+ * @throws {RangeError} for a zero divisor, a `precision` out of range, an unknown mode, or a
108
+ * rounded quotient past the exponent bound: one too large, or one whose last digit falls below
109
+ * `10^-Decimal.MAX_EXPONENT`, as `new Decimal('1e-9990').divide(3)` does at 34 digits.
110
+ * @example
111
+ * ```ts
112
+ * new Decimal(1).divide(3).toString() // '0.3333333333333333333333333333333333'
113
+ * new Decimal(2).divide(3, { precision: 2, roundingMode: 'trunc' }).toString() // '0.66'
114
+ * new Decimal(1).divide(8).toString() // '0.125'
115
+ * ```
116
+ */
117
+ divide(other: DecimalInput, options?: DivideOptions): Decimal;
118
+ /**
119
+ * The exact remainder of truncating division, with the sign of this value, as `%` gives.
120
+ * @throws {RangeError} for a zero divisor.
121
+ * @example
122
+ * ```ts
123
+ * new Decimal('7.5').remainder(2).toString() // '1.5'
124
+ * new Decimal('-7.5').remainder(2).toString() // '-1.5'
125
+ * ```
126
+ */
127
+ remainder(other: DecimalInput): Decimal;
128
+ /**
129
+ * This value with the opposite sign.
130
+ * @example
131
+ * ```ts
132
+ * new Decimal('5').negate().toString() // '-5'
133
+ * ```
134
+ */
135
+ negate(): Decimal;
136
+ /**
137
+ * The absolute value.
138
+ * @example
139
+ * ```ts
140
+ * new Decimal('-1.5').abs().toString() // '1.5'
141
+ * ```
142
+ */
143
+ abs(): Decimal;
144
+ /**
145
+ * Rounds to `digits` fractional digits; a negative count rounds to tens, hundreds, and so on.
146
+ * @param digits Fractional digits, from `-Decimal.MAX_EXPONENT` to `Decimal.MAX_PRECISION`
147
+ * (default 0).
148
+ * @param roundingMode How ties and remainders round (default `'halfEven'`).
149
+ * @throws {RangeError} for `digits` out of range, an unknown mode, or a result past the
150
+ * exponent bound.
151
+ * @example
152
+ * ```ts
153
+ * new Decimal('2.5').round().toString() // '2'
154
+ * new Decimal('2.5').round(0, 'halfExpand').toString() // '3'
155
+ * new Decimal('1234').round(-2).toString() // '1200'
156
+ * ```
157
+ */
158
+ round(digits?: number, roundingMode?: RoundingMode): Decimal;
159
+ /**
160
+ * The square root rounded to `precision` significant digits (default 34). An exact root with
161
+ * fewer digits is returned whole.
162
+ * @throws {TypeError} for `options` that is not an object.
163
+ * @throws {RangeError} for a negative value, a `precision` out of range, an unknown mode, or a
164
+ * rounded root whose last digit falls below `10^-Decimal.MAX_EXPONENT`.
165
+ * @example
166
+ * ```ts
167
+ * new Decimal(2).sqrt().toString() // '1.414213562373095048801688724209698'
168
+ * new Decimal('6.25').sqrt().toString() // '2.5'
169
+ * new Decimal(2).sqrt({ precision: 5 }).toString() // '1.4142'
170
+ * ```
171
+ */
172
+ sqrt(options?: DivideOptions): Decimal;
173
+ /**
174
+ * Orders this value against `other`: -1, 0 or 1.
175
+ * @example
176
+ * ```ts
177
+ * new Decimal('1.10').compare('1.1') // 0
178
+ * new Decimal('-2').compare(1) // -1
179
+ * ```
180
+ */
181
+ compare(other: DecimalInput): -1 | 0 | 1;
182
+ /**
183
+ * True when both are the same number, whatever their written form.
184
+ * @example
185
+ * ```ts
186
+ * new Decimal('2.50').equals('2.5') // true
187
+ * ```
188
+ */
189
+ equals(other: DecimalInput): boolean;
190
+ /**
191
+ * True when this value is less than `other`.
192
+ * @example
193
+ * ```ts
194
+ * new Decimal('0.1').lessThan('0.2') // true
195
+ * ```
196
+ */
197
+ lessThan(other: DecimalInput): boolean;
198
+ /**
199
+ * True when this value is less than or equal to `other`.
200
+ * @example
201
+ * ```ts
202
+ * new Decimal('0.2').lessThanOrEqual('0.20') // true
203
+ * ```
204
+ */
205
+ lessThanOrEqual(other: DecimalInput): boolean;
206
+ /**
207
+ * True when this value is greater than `other`.
208
+ * @example
209
+ * ```ts
210
+ * new Decimal('1e3').greaterThan(999) // true
211
+ * ```
212
+ */
213
+ greaterThan(other: DecimalInput): boolean;
214
+ /**
215
+ * True when this value is greater than or equal to `other`.
216
+ * @example
217
+ * ```ts
218
+ * new Decimal('-0').greaterThanOrEqual(0) // true
219
+ * ```
220
+ */
221
+ greaterThanOrEqual(other: DecimalInput): boolean;
222
+ /**
223
+ * The canonical string: plain notation while that pads at most 64 zeros, scientific past that
224
+ * (`'1e+65'`, `'1.5e-70'`), so its length follows the significant digits and not the exponent.
225
+ * The constructor reads both forms back.
226
+ * @example
227
+ * ```ts
228
+ * new Decimal('1.50').toString() // '1.5'
229
+ * new Decimal('1e100').toString() // '1e+100'
230
+ * ```
231
+ */
232
+ toString(): string;
233
+ /**
234
+ * Plain notation at any magnitude. A short input such as `'1e10000'` expands to 10,001
235
+ * characters, so prefer {@link Decimal.toString} for untrusted values.
236
+ * @example
237
+ * ```ts
238
+ * new Decimal('1e5').toPlainString() // '100000'
239
+ * new Decimal('-1.5e-3').toPlainString() // '-0.0015'
240
+ * ```
241
+ */
242
+ toPlainString(): string;
243
+ /**
244
+ * Plain notation with exactly `digits` fractional digits. Ties round half away from zero
245
+ * (`'halfExpand'`), as `Number.prototype.toFixed` rounds, not half to even as
246
+ * {@link Decimal.round} does by default; pass `roundingMode` to choose another.
247
+ * @param digits Fractional digits, from 0 to `Decimal.MAX_PRECISION` (default 0).
248
+ * @param roundingMode How the last digit rounds (default `'halfExpand'`).
249
+ * @throws {RangeError} for `digits` out of range or an unknown mode.
250
+ * @example
251
+ * ```ts
252
+ * new Decimal('2.5').toFixed() // '3'
253
+ * new Decimal('1.005').toFixed(2) // '1.01'
254
+ * new Decimal('3').toFixed(2) // '3.00'
255
+ * ```
256
+ */
257
+ toFixed(digits?: number, roundingMode?: RoundingMode): string;
258
+ /** The canonical string, as {@link Decimal.toString}, so `JSON.stringify` keeps every digit. */
259
+ toJSON(): string;
260
+ /**
261
+ * Formats the exact value with `Intl.NumberFormat`, which reads decimal strings without going
262
+ * through a `Number`, so digits past 2^53 survive.
263
+ * @throws {RangeError} when the value is beyond `Number.MAX_VALUE`, which `Intl` shows as `∞`,
264
+ * or so close to zero that it rounds to a `Number` zero, which `Intl` may show as `0`.
265
+ * @throws {RangeError} for a malformed locale tag, or a locale list longer than 255 characters
266
+ * joined, which `Intl` canonicalizes in quadratic time.
267
+ * @throws {TypeError} for a locale that is neither a string nor an `Intl.Locale`.
268
+ * @example
269
+ * ```ts
270
+ * new Decimal('12345678901234567.25').toLocaleString('en-US', { maximumFractionDigits: 2 })
271
+ * // '12,345,678,901,234,567.25'
272
+ * ```
273
+ */
274
+ toLocaleString(locales?: Intl.LocalesArgument, options?: Intl.NumberFormatOptions): string;
275
+ /**
276
+ * The nearest `Number`, read from the coefficient and exponent, so extreme exponents stay cheap.
277
+ * @example
278
+ * ```ts
279
+ * new Decimal('0.1').toNumber() // 0.1
280
+ * new Decimal('1e400').toNumber() // Infinity
281
+ * ```
282
+ */
283
+ toNumber(): number;
284
+ /**
285
+ * The value as a bigint.
286
+ * @throws {RangeError} when the value has a fractional part.
287
+ * @example
288
+ * ```ts
289
+ * new Decimal('1.2e3').toBigInt() // 1200n
290
+ * ```
291
+ */
292
+ toBigInt(): bigint;
293
+ /**
294
+ * Throws, so `<`, `+` and `==` cannot silently turn a Decimal into a lossy `Number`. Use
295
+ * {@link Decimal.compare}, {@link Decimal.add} or {@link Decimal.toNumber}.
296
+ * @throws {TypeError} always.
297
+ */
298
+ valueOf(): never;
299
+ }