|
| 1 | +'use strict'; |
| 2 | + |
| 3 | +interface Options { |
| 4 | + from: string; |
| 5 | + to: string; |
| 6 | + base: string; |
| 7 | + rates: object; |
| 8 | +} |
| 9 | + |
| 10 | +function hasKey<T>(obj: T, key: keyof any): key is keyof T { |
| 11 | + return key in obj; |
| 12 | +} |
| 13 | + |
| 14 | +const getRate = ({base, rates, from, to}: Options): number => { |
| 15 | + if (hasKey(rates, from) && hasKey(rates, to)) { |
| 16 | + // If `from` equals `base`, return the basic exchange rate for the `to` currency |
| 17 | + if (from === base) { |
| 18 | + return rates[to]; |
| 19 | + } |
| 20 | + |
| 21 | + // If `to` equals `base`, return the basic inverse rate of the `from` currency |
| 22 | + if (to === base) { |
| 23 | + return 1 / rates[from]; |
| 24 | + } |
| 25 | + |
| 26 | + /** |
| 27 | + Otherwise, return the `to` rate multipled by the inverse of the `from` rate to get the |
| 28 | + relative exchange rate between the two currencies |
| 29 | + */ |
| 30 | + return rates[to] * (1 / rates[from]); |
| 31 | + } |
| 32 | + |
| 33 | + throw new Error('Rates do not contain either `from` or `to` currency!'); |
| 34 | +}; |
| 35 | + |
| 36 | +class Cashify { |
| 37 | + /** |
| 38 | + * @param {string} base Base currency |
| 39 | + * @param {object} rates Object containing currency rates (for example from an API, such as Open Exchange Rates) |
| 40 | + */ |
| 41 | + |
| 42 | + public readonly options: Omit<Options, 'from' | 'to'>; |
| 43 | + |
| 44 | + constructor({base, rates}: Omit<Options, 'from' | 'to'>) { |
| 45 | + this.options = { |
| 46 | + base, |
| 47 | + rates |
| 48 | + }; |
| 49 | + } |
| 50 | + |
| 51 | + /** |
| 52 | + * @param {number} amount Amount of money you want to convert |
| 53 | + * @param {object} options Conversion options |
| 54 | + * @param {string} options.from Currency from which you want to convert |
| 55 | + * @param {string} options.to Currency to which you want to convert |
| 56 | + * @return {number} Conversion result |
| 57 | + */ |
| 58 | + convert(amount: number, {from, to}: Omit<Options, 'base' | 'rates'>): number { |
| 59 | + const {base, rates} = this.options; |
| 60 | + |
| 61 | + return amount * getRate({base, rates, from, to}); |
| 62 | + } |
| 63 | +} |
| 64 | + |
| 65 | +export default Cashify; |
0 commit comments