@eriveltondasilva/currency 1.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.
@@ -0,0 +1,662 @@
1
+ /**
2
+ * @ERIVELTONDASILVA/CURRENCY v1.0.0
3
+ *
4
+ * A lightweight and reliable JavaScript library for precise currency operations, built to safely handle monetary values without floating point errors.
5
+ *
6
+ * @author Erivelton Silva <eriveltondasilva13@gmail.com>
7
+ * @license MIT
8
+ * @copyright 2026 Erivelton Silva
9
+ * @version 1.0.0
10
+ *
11
+ * @see https://github.com/eriveltondasilva/currency#readme - Documentation
12
+ *
13
+ * Inspired by:
14
+ * @see https://github.com/scurker/currency.js
15
+ */
16
+
17
+ type CountryCode = 'AU' | 'BR' | 'CA' | 'CH' | 'CN' | 'DE' | 'FR' | 'GB' | 'IN' | 'JP' | 'MX' | 'SG' | 'PT' | 'US';
18
+ type CurrencyCode = 'AUD' | 'BRL' | 'CAD' | 'CHF' | 'CNY' | 'EUR' | 'GBP' | 'INR' | 'JPY' | 'MXN' | 'SGD' | 'USD';
19
+
20
+ /**
21
+ * Accepted input for monetary operations.
22
+ *
23
+ * Pass a `number` (major units, e.g. `19.99`) or an existing `MoneyContract`
24
+ * instance. When a `MoneyContract` is passed, the currency must match the
25
+ * receiver's currency — otherwise a `CurrencyMismatchError` is thrown.
26
+ */
27
+ type MoneyInput = number | MoneyContract;
28
+ /**
29
+ * Controls how a value is rounded when it falls between two representable steps.
30
+ *
31
+ * **Direction-based** (always rounds regardless of the fractional part):
32
+ * - `'ceil'` — toward +∞ ( 1.1 → 2, -1.1 → -1)
33
+ * - `'floor'` — toward -∞ ( 1.1 → 1, -1.1 → -2)
34
+ * - `'trunc'` — toward 0 ( 1.9 → 1, -1.9 → -1)
35
+ * - `'expand'` — away from 0 ( 1.1 → 2, -1.1 → -2)
36
+ *
37
+ * **Nearest-neighbor** (tie-breaking at .5):
38
+ * - `'halfExpand'` — half away from 0 — **default**; symmetric and human-friendly
39
+ * ( 1.5 → 2, -1.5 → -2)
40
+ * - `'halfEven'` — half to nearest even (banker's rounding); reduces statistical bias
41
+ * ( 1.5 → 2, 2.5 → 2)
42
+ * - `'halfCeil'` — half toward +∞; matches `Math.round`, asymmetric for negatives
43
+ * ( 1.5 → 2, -1.5 → -1)
44
+ * - `'halfFloor'` — half toward -∞; asymmetric for positives
45
+ * ( 1.5 → 1, -1.5 → -2)
46
+ * - `'halfTrunc'` — half toward 0; asymmetric in both directions
47
+ * ( 1.5 → 1, -1.5 → -1)
48
+ */
49
+ type RoundingMode = 'ceil' | 'floor' | 'trunc' | 'expand' | 'halfExpand' | 'halfEven' | 'halfCeil' | 'halfFloor' | 'halfTrunc';
50
+ /**
51
+ * Display options passed to {@link MoneyContract.format}.
52
+ *
53
+ * All properties are optional. Unset properties fall back to locale-aware
54
+ * defaults derived from the instance's currency.
55
+ */
56
+ interface FormatOptions {
57
+ /**
58
+ * Override the locale used for display only.
59
+ * Does **not** affect internal values or currency code.
60
+ *
61
+ * @example
62
+ * `'en-US'`, `'pt-BR'`, `'de-DE'`
63
+ */
64
+ locale?: string;
65
+ /**
66
+ * Controls how the currency identifier is rendered.
67
+ *
68
+ * - `'symbol'` — `R$`, `$`, `€`
69
+ * - `'narrowSymbol'` — `$` (shorter; avoids regional ambiguity)
70
+ * - `'code'` — `BRL`, `USD`, `EUR`
71
+ * - `'name'` — `real brasileiro`, `US dollar`
72
+ * - `'none'` — no currency indicator (decimal style)
73
+ *
74
+ * @default 'symbol'
75
+ */
76
+ currencyDisplay?: 'symbol' | 'narrowSymbol' | 'code' | 'name' | 'none';
77
+ /**
78
+ * Controls the number notation format.
79
+ *
80
+ * - `'standard'` — `1.500.000,00`
81
+ * - `'compact'` — `1,5 mi` / `1.5M`; useful for dashboards
82
+ *
83
+ * @default 'standard'
84
+ */
85
+ notation?: 'standard' | 'compact';
86
+ /**
87
+ * Controls when the sign character is displayed.
88
+ *
89
+ * - `'auto'` — only negative values show a sign
90
+ * - `'always'` — `+R$ 100,00` / `-R$ 50,00`
91
+ * - `'exceptZero'` — sign on all non-zero values
92
+ * - `'negative'` — only negative; no `+` for positives
93
+ *
94
+ * @default 'auto'
95
+ */
96
+ signDisplay?: 'auto' | 'always' | 'exceptZero' | 'negative';
97
+ /**
98
+ * Whether to render digit-grouping separators (e.g. `1.000` vs `1000`).
99
+ *
100
+ * @default true
101
+ */
102
+ useGrouping?: boolean | 'always' | 'auto' | 'min2';
103
+ /**
104
+ * `'accounting'` renders negatives in parentheses: `(R$ 50,00)`.
105
+ *
106
+ * @default 'standard'
107
+ */
108
+ currencySign?: 'standard' | 'accounting';
109
+ /**
110
+ * Unit label for compact notation.
111
+ *
112
+ * @default 'short'
113
+ */
114
+ compactDisplay?: 'short' | 'long';
115
+ /**
116
+ * Whether to strip trailing zeros when the value is a whole number.
117
+ *
118
+ * @default 'auto'
119
+ */
120
+ trailingZeroDisplay?: 'auto' | 'stripIfInteger';
121
+ /**
122
+ * Rounding mode applied during formatting.
123
+ *
124
+ * @default 'halfExpand'
125
+ */
126
+ roundingMode?: RoundingMode;
127
+ /**
128
+ * Minimum number of fraction digits to display.
129
+ *
130
+ * @default currency.fractionDigits
131
+ */
132
+ minimumFractionDigits?: number;
133
+ /**
134
+ * Maximum number of fraction digits to display.
135
+ *
136
+ * @default currency.fractionDigits
137
+ */
138
+ maximumFractionDigits?: number;
139
+ }
140
+ /**
141
+ * Represents an item with a price and an optional integer quantity.
142
+ * Used as input for {@link total}.
143
+ */
144
+ interface PricedItem {
145
+ /** Unit price of the item, as a number (major units) or a `MoneyContract` instance. */
146
+ price: MoneyInput;
147
+ /**
148
+ * Number of units. Must be a **non-negative integer**.
149
+ * Fractional quantities are rejected at runtime with `InvalidInputError`.
150
+ *
151
+ * @default 1
152
+ */
153
+ quantity?: number;
154
+ }
155
+ /**
156
+ * Plain-object representation of a `MoneyContract`, safe for JSON serialization.
157
+ * Use with {@link MoneyContract.toJSON} and `Money.fromMinorUnits` for round-tripping.
158
+ *
159
+ * @example
160
+ * const json = money.toJSON();
161
+ * // => { minorUnits: 1999, currencyCode: 'BRL' }
162
+ */
163
+ interface MoneyJSON {
164
+ /** Internal integer value (e.g. `1999` represents `R$ 19,99`). */
165
+ minorUnits: number;
166
+ /** ISO 4217 currency code. */
167
+ currencyCode: CurrencyCode;
168
+ }
169
+ type MoneyComparison = -1 | 0 | 1;
170
+ /**
171
+ * Tuple of `[units, subunits]` returned by {@link MoneyContract.toParts}.
172
+ *
173
+ * Both values are always **non-negative integers**, regardless of the sign of
174
+ * the underlying amount.
175
+ *
176
+ * @example
177
+ * from(19.99, 'BR').toParts() // => [19, 99]
178
+ * from(-5.07, 'US').toParts() // => [5, 7]
179
+ */
180
+ interface MoneyParts {
181
+ units: number;
182
+ subunits: number;
183
+ isNegative: boolean;
184
+ }
185
+ /**
186
+ * Public contract for all monetary value objects produced by this library.
187
+ *
188
+ * Instances are **immutable**: every operation returns a new `MoneyContract`.
189
+ * Values are stored internally as minor units (safe integers) to prevent
190
+ * floating-point errors.
191
+ *
192
+ * Supported countries:
193
+ *
194
+ * `AU`, `BR`, `CA`, `CH`, `CN`, `DE`, `FR`, `GB`, `IN`, `JP`, `MX`, `PT`, `SG`, `US`.
195
+ */
196
+ interface MoneyContract {
197
+ /**
198
+ * Returns the raw internal integer (minor units).
199
+ *
200
+ * @returns An integer such that `minorUnits / 10^fractionDigits === amount()`.
201
+ *
202
+ * @example
203
+ * from(19.99, 'BR').minorUnits() // => 1999
204
+ * from(100, 'JP').minorUnits() // => 100 (JPY has 0 fraction digits)
205
+ */
206
+ minorUnits(): number;
207
+ /**
208
+ * Returns the monetary amount in major units.
209
+ *
210
+ * @returns A floating-point number (e.g. `19.99`). For display, prefer {@link format}.
211
+ *
212
+ * @example
213
+ * from(19.99, 'BR').amount() // => 19.99
214
+ */
215
+ amount(): number;
216
+ /**
217
+ * Returns the whole-unit part of the amount, always non-negative.
218
+ *
219
+ * @returns A non-negative integer (e.g. `19` for `R$ 19,99`).
220
+ *
221
+ * @example
222
+ * from(19.99, 'BR').units() // => 19
223
+ * from(-5.07, 'US').units() // => 5
224
+ */
225
+ units(): number;
226
+ /**
227
+ * Returns the sub-unit part of the amount, always non-negative.
228
+ *
229
+ * @returns A non-negative integer (e.g. `99` for `R$ 19,99`).
230
+ *
231
+ * @example
232
+ * from(19.99, 'BR').subunits() // => 99
233
+ * from(-5.07, 'US').subunits() // => 7
234
+ */
235
+ subunits(): number;
236
+ /**
237
+ * Returns the amount split into its constituent parts.
238
+ *
239
+ * `units` and `subunits` are always non-negative integers.
240
+ * Use `negative` to determine the sign of the original amount.
241
+ *
242
+ * @returns A `MoneyParts` object with `units`, `subunits`, and `negative`.
243
+ *
244
+ * @example
245
+ * from( 19.99, 'BR').toParts() // => { units: 19, subunits: 99, negative: false }
246
+ * from(-19.99, 'BR').toParts() // => { units: 19, subunits: 99, negative: true }
247
+ * from( -0.99, 'US').toParts() // => { units: 0, subunits: 99, negative: true }
248
+ * from( 0, 'US').toParts() // => { units: 0, subunits: 0, negative: false }
249
+ */
250
+ toParts(): MoneyParts;
251
+ /**
252
+ * Returns the ISO 4217 currency code of this instance.
253
+ *
254
+ * @returns A currency code string such as `'BRL'` or `'USD'`.
255
+ *
256
+ * @example
257
+ * from(10, 'BR').currencyCode() // => 'BRL'
258
+ */
259
+ currencyCode(): CurrencyCode;
260
+ /**
261
+ * Returns the BCP 47 locale tag associated with this instance's country.
262
+ *
263
+ * @returns A locale string such as `'pt-BR'` or `'en-US'`.
264
+ *
265
+ * @example
266
+ * from(10, 'BR').locale() // => 'pt-BR'
267
+ */
268
+ locale(): string;
269
+ /**
270
+ * Returns `true` if the amount is exactly zero.
271
+ *
272
+ * @example
273
+ * from(0, 'BR').isZero() // => true
274
+ * from(0.01, 'BR').isZero() // => false
275
+ */
276
+ isZero(): boolean;
277
+ /**
278
+ * Returns `true` if the amount is greater than zero.
279
+ *
280
+ * @example
281
+ * from(1, 'US').isPositive() // => true
282
+ * from(-1, 'US').isPositive() // => false
283
+ */
284
+ isPositive(): boolean;
285
+ /**
286
+ * Returns `true` if the amount is less than zero.
287
+ *
288
+ * @example
289
+ * from(-1, 'US').isNegative() // => true
290
+ * from(1, 'US').isNegative() // => false
291
+ */
292
+ isNegative(): boolean;
293
+ /**
294
+ * Adds a monetary value to this instance.
295
+ *
296
+ * @param input - Amount to add. A `number` is interpreted as major units.
297
+ *
298
+ * @returns A new `MoneyContract` with the sum.
299
+ *
300
+ * @throws `CurrencyMismatchError` - when `input` is a `MoneyContract` with a different currency.
301
+ * @throws `InvalidInputError` - when the result is not a finite number.
302
+ * @throws `UnsafeIntegerError` - when the result exceeds `Number.MAX_SAFE_INTEGER`.
303
+ *
304
+ * @example
305
+ * from(10, 'BR').plus(5).amount() // => 15
306
+ * from(10, 'BR').plus(from(5, 'BR')).amount() // => 15
307
+ */
308
+ plus(input: MoneyInput): MoneyContract;
309
+ /**
310
+ * Subtracts a monetary value from this instance.
311
+ *
312
+ * @param input - Amount to subtract. A `number` is interpreted as major units.
313
+ *
314
+ * @returns A new `MoneyContract` with the difference.
315
+ *
316
+ * @throws `CurrencyMismatchError` - when `input` is a `MoneyContract` with a different currency.
317
+ * @throws `UnsafeIntegerError` - when the result exceeds `Number.MAX_SAFE_INTEGER`.
318
+ *
319
+ * @example
320
+ * from(10, 'US').minus(3.50).amount() // => 6.5
321
+ */
322
+ minus(input: MoneyInput): MoneyContract;
323
+ /**
324
+ * Multiplies this instance by a scalar factor.
325
+ *
326
+ * The result is rounded in minor units using the specified `roundingMode`.
327
+ * Defaults to `'halfExpand'`.
328
+ *
329
+ * @param factor - Finite scalar multiplier.
330
+ * @param roundingMode - Rounding strategy applied to the minor-unit result. Defaults to `'halfExpand'`.
331
+ *
332
+ * @returns A new `MoneyContract` with the product.
333
+ *
334
+ * @throws `InvalidInputError` - when `factor` is not finite.
335
+ * @throws `UnsafeIntegerError` - when the result exceeds `Number.MAX_SAFE_INTEGER`.
336
+ *
337
+ * @example
338
+ * from(10, 'BR').times(1.5).amount() // => 15
339
+ * from(1, 'US').times(1/3, 'halfEven').amount() // => 0.33
340
+ */
341
+ times(factor: number, roundingMode?: RoundingMode): MoneyContract;
342
+ /**
343
+ * Divides this instance by a scalar divisor.
344
+ *
345
+ * The result is rounded in minor units using the specified `roundingMode`.
346
+ * Defaults to `'halfExpand'`.
347
+ *
348
+ * @param divisor - Finite, non-zero scalar.
349
+ * @param roundingMode - Rounding strategy applied to the minor-unit result. Defaults to `'halfExpand'`.
350
+ *
351
+ * @returns A new `MoneyContract` with the quotient.
352
+ *
353
+ * @throws `DivisionByZeroError` - when `divisor` is `0`.
354
+ * @throws `InvalidInputError` - when `divisor` is not finite.
355
+ * @throws `UnsafeIntegerError` - when the result exceeds `Number.MAX_SAFE_INTEGER`.
356
+ *
357
+ * @example
358
+ * from(10, 'BR').divide(4).amount() // => 2.5
359
+ * from(1, 'US').divide(3).amount() // => 0.33
360
+ */
361
+ divide(divisor: number, roundingMode?: RoundingMode): MoneyContract;
362
+ /**
363
+ * Returns a new instance with the absolute (non-negative) amount.
364
+ *
365
+ * @returns A new `MoneyContract` with `amount >= 0`.
366
+ *
367
+ * @example
368
+ * from(-15, 'US').abs().amount() // => 15
369
+ */
370
+ abs(): MoneyContract;
371
+ /**
372
+ * Returns a new instance with the sign of the amount flipped.
373
+ *
374
+ * @returns A new `MoneyContract` with the negated amount.
375
+ *
376
+ * @example
377
+ * from(20, 'BR').negate().amount() // => -20
378
+ * from(-20, 'BR').negate().amount() // => 20
379
+ */
380
+ negate(): MoneyContract;
381
+ /**
382
+ * Returns the greater of this instance and `input`.
383
+ *
384
+ * @param input - Comparison value. A `number` is interpreted as major units.
385
+ *
386
+ * @returns The larger of the two values as a new `MoneyContract`.
387
+ *
388
+ * @throws `CurrencyMismatchError` - when `input` is a `MoneyContract` with a different currency.
389
+ *
390
+ * @example
391
+ * from(5, 'US').max(10).amount() // => 10
392
+ * from(5, 'US').max(3).amount() // => 5
393
+ */
394
+ max(input: MoneyInput): MoneyContract;
395
+ /**
396
+ * Returns the lesser of this instance and `input`.
397
+ *
398
+ * @param input - Comparison value. A `number` is interpreted as major units.
399
+ *
400
+ * @returns The smaller of the two values as a new `MoneyContract`.
401
+ *
402
+ * @throws `CurrencyMismatchError` - when `input` is a `MoneyContract` with a different currency.
403
+ *
404
+ * @example
405
+ * from(5, 'US').min(10).amount() // => 5
406
+ * from(5, 'US').min(3).amount() // => 3
407
+ */
408
+ min(input: MoneyInput): MoneyContract;
409
+ /**
410
+ * Rounds the amount to the nearest multiple of `step` in major units.
411
+ *
412
+ * Useful for currencies or payment systems that require rounding to specific
413
+ * denominations (e.g. rounding to the nearest $0.05 or $1.00).
414
+ *
415
+ * @param step — Positive number in major units specifying the rounding step.
416
+ * @param mode — Rounding strategy. Defaults to `'halfExpand'`.
417
+ *
418
+ * @returns A new `MoneyContract` rounded to the nearest `step`.
419
+ *
420
+ * @throws `InvalidInputError` — when `step` is not a positive finite number,
421
+ * or too small to be represented in minor units for this currency.
422
+ *
423
+ * @example
424
+ * from(1.03, 'US').round(0.05).amount() // => 1.05 (nearest 5 cents)
425
+ * from(1.02, 'US').round(0.05).amount() // => 1.00 (nearest 5 cents)
426
+ * from(1.50, 'US').round(1).amount() // => 2.00 (nearest dollar)
427
+ * from(1499, 'BR').round(500).amount() // => 1500 (nearest R$ 500)
428
+ */
429
+ round(step: number, mode?: RoundingMode): MoneyContract;
430
+ /**
431
+ * Returns `true` if this instance represents the same amount and currency as `input`.
432
+ *
433
+ * When `input` is a `MoneyContract` with a different currency, returns `false`
434
+ * instead of throwing.
435
+ *
436
+ * @param input - Value to compare. A `number` is interpreted as major units.
437
+ *
438
+ * @example
439
+ * from(10, 'BR').equals(10) // => true
440
+ * from(10, 'BR').equals(from(10, 'US')) // => false
441
+ */
442
+ equals(input: MoneyInput): boolean;
443
+ /**
444
+ * Compares this instance to `input` for ordering purposes.
445
+ *
446
+ * Returns `-1` when less than, `0` when equal, or `1` when greater than `input`.
447
+ * Designed for direct use as an `Array.sort` comparator.
448
+ *
449
+ * @param input — Comparison value. A `number` is interpreted as major units.
450
+ *
451
+ * @returns `-1`, `0`, or `1`.
452
+ *
453
+ * @throws `CurrencyMismatchError` — when `input` is a `MoneyContract` with a different currency.
454
+ *
455
+ * @example
456
+ * from(10, 'US').compare(20) // => -1
457
+ * from(10, 'US').compare(10) // => 0
458
+ * from(20, 'US').compare(10) // => 1
459
+ *
460
+ * // Sorting
461
+ * prices.sort((a, b) => a.compare(b)) // ascending
462
+ * prices.sort((a, b) => b.compare(a)) // descending
463
+ */
464
+ compare(other: MoneyInput): MoneyComparison;
465
+ /**
466
+ * Returns `true` if this instance is strictly greater than `input`.
467
+ *
468
+ * @param input - Comparison value. A `number` is interpreted as major units.
469
+ *
470
+ * @throws `CurrencyMismatchError` - when `input` is a `MoneyContract` with a different currency.
471
+ *
472
+ * @example
473
+ * from(10, 'US').greaterThan(5) // => true
474
+ */
475
+ greaterThan(input: MoneyInput): boolean;
476
+ /**
477
+ * Returns `true` if this instance is strictly less than `input`.
478
+ *
479
+ * @param input - Comparison value. A `number` is interpreted as major units.
480
+ *
481
+ * @throws `CurrencyMismatchError` - when `input` is a `MoneyContract` with a different currency.
482
+ *
483
+ * @example
484
+ * from(3, 'US').lessThan(10) // => true
485
+ */
486
+ lessThan(input: MoneyInput): boolean;
487
+ /**
488
+ * Returns `true` if this instance is greater than or equal to `input`.
489
+ *
490
+ * @param input - Comparison value. A `number` is interpreted as major units.
491
+ *
492
+ * @throws `CurrencyMismatchError` - when `input` is a `MoneyContract` with a different currency.
493
+ *
494
+ * @example
495
+ * from(10, 'US').greaterThanOrEqual(10) // => true
496
+ */
497
+ greaterThanOrEqual(input: MoneyInput): boolean;
498
+ /**
499
+ * Returns `true` if this instance is less than or equal to `input`.
500
+ *
501
+ * @param input - Comparison value. A `number` is interpreted as major units.
502
+ *
503
+ * @throws `CurrencyMismatchError` - when `input` is a `MoneyContract` with a different currency.
504
+ *
505
+ * @example
506
+ * from(5, 'US').lessThanOrEqual(10) // => true
507
+ */
508
+ lessThanOrEqual(input: MoneyInput): boolean;
509
+ /**
510
+ * Returns `true` if this instance falls within the closed interval `[min, max]`.
511
+ *
512
+ * @param min - Lower bound. A `number` is interpreted as major units.
513
+ * @param max - Upper bound. A `number` is interpreted as major units.
514
+ *
515
+ * @throws `InvalidRangeError` - when `min` is greater than `max`.
516
+ * @throws `CurrencyMismatchError` - when either bound is a `MoneyContract` with a different currency.
517
+ *
518
+ * @example
519
+ * from(5, 'US').isBetween(1, 10) // => true
520
+ * from(11, 'US').isBetween(1, 10) // => false
521
+ */
522
+ isBetween(min: MoneyInput, max: MoneyInput): boolean;
523
+ /**
524
+ * Returns `true` if `input` shares the same currency as this instance.
525
+ *
526
+ * @param other - Another `MoneyContract` to compare against.
527
+ *
528
+ * @example
529
+ * from(10, 'BR').hasSameCurrency(from(20, 'BR')) // => true
530
+ * from(10, 'BR').hasSameCurrency(from(20, 'US')) // => false
531
+ */
532
+ hasSameCurrency(other: MoneyContract): boolean;
533
+ /**
534
+ * Returns the given percentage of this instance's amount.
535
+ *
536
+ * The result is rounded in minor units. Defaults to `'halfExpand'`.
537
+ *
538
+ * @param percent - Non-negative finite number representing a percentage (e.g. `15` for 15%).
539
+ * @param roundingMode - Rounding strategy. Defaults to `'halfExpand'`.
540
+ *
541
+ * @returns A new `MoneyContract` representing the percentage amount.
542
+ *
543
+ * @throws `InvalidPercentageError` - when `percent` is negative or not finite.
544
+ *
545
+ * @example
546
+ * from(200, 'BR').percentOf(15).amount() // => 30
547
+ * from(100, 'US').percentOf(33).amount() // => 33
548
+ */
549
+ percentOf(percent: number, roundingMode?: RoundingMode): MoneyContract;
550
+ /**
551
+ * Applies a percentage discount and returns the reduced amount.
552
+ *
553
+ * Equivalent to `minus(percentOf(discount))`. The result is rounded in minor
554
+ * units using `roundingMode`. Defaults to `'halfExpand'`.
555
+ *
556
+ * @param discount - Discount percentage between `0` and `100` inclusive.
557
+ * @param roundingMode - Rounding strategy. Defaults to `'halfExpand'`.
558
+ *
559
+ * @returns A new `MoneyContract` with the discount applied.
560
+ *
561
+ * @throws `InvalidPercentageError` - when `discount` is negative, exceeds 100, or is not finite.
562
+ *
563
+ * @example
564
+ * from(100, 'US').applyDiscount(20).amount() // => 80
565
+ * from(50, 'BR').applyDiscount(10).amount() // => 45
566
+ */
567
+ applyDiscount(discount: number, roundingMode?: RoundingMode): MoneyContract;
568
+ /**
569
+ * Applies a percentage surcharge and returns the increased amount.
570
+ *
571
+ * Equivalent to `plus(percentOf(surcharge))`. The result is rounded in minor
572
+ * units using `roundingMode`. Defaults to `'halfExpand'`.
573
+ *
574
+ * @param surcharge - Non-negative surcharge percentage (e.g. `10` for +10%).
575
+ * @param roundingMode - Rounding strategy. Defaults to `'halfExpand'`.
576
+ *
577
+ * @returns A new `MoneyContract` with the surcharge applied.
578
+ *
579
+ * @throws `InvalidPercentageError` - when `surcharge` is negative or not finite.
580
+ *
581
+ * @example
582
+ * from(100, 'US').applySurcharge(10).amount() // => 110
583
+ * from(50, 'BR').applySurcharge(5).amount() // => 52.5
584
+ */
585
+ applySurcharge(surcharge: number, roundingMode?: RoundingMode): MoneyContract;
586
+ /**
587
+ * Splits the amount into `parts` equal shares, distributing any remainder
588
+ * cent-by-cent to the first slots (largest-remainder method).
589
+ *
590
+ * Guarantees that the sum of all parts equals the original amount.
591
+ *
592
+ * @param parts - Positive integer number of shares.
593
+ *
594
+ * @returns An array of `parts` new `MoneyContract` instances.
595
+ *
596
+ * @throws `InvalidAllocationError` - when `parts` is not a positive integer.
597
+ *
598
+ * @example
599
+ * from(10, 'BR').allocate(3).map((m) => m.amount())
600
+ * // => [3.34, 3.33, 3.33]
601
+ */
602
+ allocate(parts: number): MoneyContract[];
603
+ /**
604
+ * Splits the amount proportionally according to `ratios`, distributing any
605
+ * remainder cent-by-cent to the first slots (largest-remainder method).
606
+ *
607
+ * Ratios must be **non-negative integers** (e.g. `[1, 2, 3]` or `[30, 70]`).
608
+ * Guarantees that the sum of all parts equals the original amount.
609
+ *
610
+ * @param ratios - Non-empty array of non-negative integers representing relative shares.
611
+ *
612
+ * @returns An array of new `MoneyContract` instances, one per ratio entry.
613
+ *
614
+ * @throws `InvalidAllocationError` - when `ratios` is empty, contains non-integers, negative values, sums to zero, or the sum exceeds `Number.MAX_SAFE_INTEGER`.
615
+ * @throws `UnsafeIntegerError` - when an intermediate calculation exceeds the safe integer range.
616
+ *
617
+ * @example
618
+ * from(100, 'US').allocateByRatio([1, 3]).map((m) => m.amount())
619
+ * // => [25, 75]
620
+ */
621
+ allocateByRatio(ratios: number[]): MoneyContract[];
622
+ /**
623
+ * Formats the amount as a locale-aware currency string using `Intl.NumberFormat`.
624
+ *
625
+ * @param options - Optional display overrides. See {@link FormatOptions}.
626
+ *
627
+ * @returns A formatted string.
628
+ *
629
+ * @example
630
+ * from(1999.9, 'BR').format() // => 'R$ 1.999,90'
631
+ * from(1999.9, 'US').format({ currencyDisplay: 'code', notation: 'compact' })
632
+ * // => 'USD 2K'
633
+ */
634
+ format(options?: FormatOptions): string;
635
+ /**
636
+ * Returns a string with the currency code and amount in major units.
637
+ *
638
+ * The number of decimal places matches the currency's `fractionDigits`.
639
+ * For display purposes, prefer {@link format}.
640
+ *
641
+ * @returns A string such as `'BRL 19.99'` or `'JPY 100'`.
642
+ *
643
+ * @example
644
+ * from(19.99, 'BR').toString() // => 'BRL 19.99'
645
+ * from(500, 'JP').toString() // => 'JPY 500'
646
+ */
647
+ toString(): string;
648
+ /**
649
+ * Returns a plain object safe for JSON serialization.
650
+ *
651
+ * Use {@link fromMinorUnits} to reconstruct the instance from this value.
652
+ *
653
+ * @returns A `MoneyJSON` object with `minorUnits` and `currencyCode`.
654
+ *
655
+ * @example
656
+ * from(19.99, 'BR').toJSON()
657
+ * // => { minorUnits: 1999, currencyCode: 'BRL' }
658
+ */
659
+ toJSON(): MoneyJSON;
660
+ }
661
+
662
+ export type { CountryCode as C, FormatOptions as F, MoneyInput as M, PricedItem as P, RoundingMode as R, MoneyContract as a };