From 37ef40acf5c37c679c60531c67228a66146b6306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gromit=20=28=EC=A0=84=EB=AF=BC=EC=9E=AC=29?= <64779472+ssi02014@users.noreply.github.com> Date: Sun, 12 Jan 2025 23:49:23 +0900 Subject: [PATCH] =?UTF-8?q?fix(utils):=20formatNumberWithCurrency=20locale?= =?UTF-8?q?=20=EA=B0=92=20=ED=83=80=EC=9E=85=EC=9D=84=20locale=20=ED=8F=AC?= =?UTF-8?q?=EB=A7=B7=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?(#671)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/rich-jobs-fry.md | 5 + .../formatter/formatNumberWithCurrency.md | 57 ++++++-- .../formatNumberWithCurrency.constants.ts | 25 ++++ .../formatNumberWithCurrency.spec.ts | 51 ++++--- .../formatNumberWithCurrency.types.ts | 5 +- .../formatNumberWithCurrency.utils.ts | 50 ++----- .../formatNumberWithCurrency/index.ts | 138 ++++++++++++++++-- .../formatNumberWithUnits.utils.ts | 13 +- .../formatter/formatNumberWithUnits/index.ts | 7 +- 9 files changed, 251 insertions(+), 100 deletions(-) create mode 100644 .changeset/rich-jobs-fry.md create mode 100644 packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.constants.ts diff --git a/.changeset/rich-jobs-fry.md b/.changeset/rich-jobs-fry.md new file mode 100644 index 000000000..683314ff0 --- /dev/null +++ b/.changeset/rich-jobs-fry.md @@ -0,0 +1,5 @@ +--- +'@modern-kit/utils': patch +--- + +fix(utils): formatNumberWithCurrency locale 값 타입을 locale 포맷에 맞게 변경 - @ssi02014 diff --git a/docs/docs/utils/formatter/formatNumberWithCurrency.md b/docs/docs/utils/formatter/formatNumberWithCurrency.md index 97465fda0..c55b5abef 100644 --- a/docs/docs/utils/formatter/formatNumberWithCurrency.md +++ b/docs/docs/utils/formatter/formatNumberWithCurrency.md @@ -2,6 +2,12 @@ `숫자` 혹은 `숫자로 이루어진 문자열`을 주어진 `통화 기호`를 추가하는 함수입니다. +기본 옵션으로 직접 원하는 형태로 숫자에 통화 기호를 추가해 포맷팅할 수 있습니다. +- 기본 옵션: `symbol`, `position`, `space`, `commas`, `decimal` + +`locale` 옵션이 있으면 `locale` 형식에 따라 포맷팅됩니다. `소수점 자리(decimal)` 옵션은 포함됩니다. +- `locale`, `decimal` 옵션을 제외한 나머지 옵션들은 무시됩니다. +
## Code @@ -9,20 +15,30 @@ ## Interface ```ts title="typescript" -type Locale = 'KRW' | 'KRW_SYMBOL' | 'USD' | 'JPY' | 'CNY' | 'EUR'; - -interface CurrencyOptions { +interface FormatNumberCurrencyOptions { symbol?: string; // default: '' position?: 'prefix' | 'suffix'; // default: 'suffix' space?: boolean; // default: false commas?: boolean; // default: true + decimal?: number; // default: 0 locale?: Locale; } ``` ```ts title="typescript" +// 옵션 없이 사용 +function formatNumberWithCurrency(value: number | string): string; + +// locale 옵션을 제외한, 기본 옵션이 주어지면 주어진 옵션에 따라 포맷팅됩니다. +// (기본 옵션: `symbol`, `position`, `space`, `commas`, `decimal`) +function formatNumberWithCurrency( + value: number | string, + options: Omit +): string; + +// locale 옵션이 있으면 locale 형식에 따라 포맷팅됩니다. function formatNumberWithCurrency( value: number | string, - options?: CurrencyOptions + options: { locale: Locale; decimal?: number } ): string; ``` @@ -50,6 +66,7 @@ formatNumberWithCurrency(-1000, { symbol: '원', position: 'suffix' }) // '-1,00
### 옵션 사용 +- 기본 옵션 사용(`symbol`, `position`, `space`, `commas`, `decimal`) ```ts title="typescript" import { formatNumberWithCurrency } from '@modern-kit/utils'; @@ -64,12 +81,28 @@ formatNumberWithCurrency(1000, { symbol: '$', position: 'prefix', space: true }) formatNumberWithCurrency(1000, { symbol: '원', commas: false }) // '1000원' formatNumberWithCurrency(1000, { symbol: '원', commas: true }) // '1,000원' -// locale 사용 -// locale 옵션이 있으면 commas 옵션을 제외한 나머지 옵션들은 무시됩니다. -formatNumberWithCurrency(1000, { locale: 'USD' }) // '$1,000' -formatNumberWithCurrency(1000, { locale: 'KRW' }) // '1,000원' -formatNumberWithCurrency(1000, { locale: 'KRW_SYMBOL' }) // '1,000₩' -formatNumberWithCurrency(1000, { locale: 'JPY' }) // '¥1,000' -formatNumberWithCurrency(1000, { locale: 'CNY' }) // '¥1,000' -formatNumberWithCurrency(1000, { locale: 'EUR' }) // '€1,000' +// 소숫점 자리수 포맷팅 (기본값: 0) +formatNumberWithCurrency(1000.234, { symbol: '원', decimal: 3 }) // '1,000.234원' +formatNumberWithCurrency(1000.234, { symbol: '원', decimal: 0 }) // '1,000원' +``` + +
+ +### 옵션 사용2 +- `locale` 옵션 사용 +```ts title="typescript" +import { formatNumberWithCurrency } from '@modern-kit/utils'; + +// locale 옵션이 있으면 locale 형식에 따라 포맷팅됩니다. +formatNumberWithCurrency(1000, { locale: 'en-US' }) // '$1,000' +formatNumberWithCurrency(1000, { locale: 'ko-KR-UNIT' }) // '1,000원' +formatNumberWithCurrency(1000, { locale: 'ko-KR' }) // '₩1,000' +formatNumberWithCurrency(1000, { locale: 'ja-JP' }) // '¥1,000' +formatNumberWithCurrency(1000, { locale: 'zh-CN' }) // '¥1,000' +formatNumberWithCurrency(1000, { locale: 'zh-HK' }) // 'HK$1,000' +formatNumberWithCurrency(1000, { locale: 'en-GB' }) // '£1,000' + +// 소숫점 자리수 포맷팅 (기본값: 0) +formatNumberWithCurrency(1000.234, { locale: 'en-US', decimal: 3 }) // '$1,000.234' +formatNumberWithCurrency(1000.234, { locale: 'en-US', decimal: 0 }) // '$1,000' ``` diff --git a/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.constants.ts b/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.constants.ts new file mode 100644 index 000000000..c6bfb84d8 --- /dev/null +++ b/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.constants.ts @@ -0,0 +1,25 @@ +export const LOCALE_CURRENCY_MAP = { + 'ko-KR': { currency: 'KRW' }, // 대한민국 + 'en-US': { currency: 'USD' }, // 미국 + 'ja-JP': { currency: 'JPY' }, // 일본 + 'zh-CN': { currency: 'CNY' }, // 중국 + 'de-DE': { currency: 'EUR' }, // 독일 + 'en-GB': { currency: 'GBP' }, // 영국 + 'fr-FR': { currency: 'EUR' }, // 프랑스 + 'it-IT': { currency: 'EUR' }, // 이탈리아 + 'es-ES': { currency: 'EUR' }, // 스페인 + 'nl-NL': { currency: 'EUR' }, // 네덜란드 + 'pt-PT': { currency: 'EUR' }, // 포르투갈 + 'zh-HK': { currency: 'HKD' }, // 홍콩 + 'ru-RU': { currency: 'RUB' }, // 러시아 + 'ar-SA': { currency: 'SAR' }, // 사우디아라비아 + 'tr-TR': { currency: 'TRY' }, // 터키 + 'vi-VN': { currency: 'VND' }, // 베트남 + 'th-TH': { currency: 'THB' }, // 태국 + 'id-ID': { currency: 'IDR' }, // 인도네시아 + 'my-MY': { currency: 'MYR' }, // 말레이시아 + 'ph-PH': { currency: 'PHP' }, // 필리핀 + 'sg-SG': { currency: 'SGD' }, // 싱가포르 + 'nz-NZ': { currency: 'NZD' }, // 뉴질랜드 + // 필요 시 추가 +} as const; diff --git a/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.spec.ts b/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.spec.ts index cf63fc08c..cc4565d31 100644 --- a/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.spec.ts +++ b/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.spec.ts @@ -1,5 +1,6 @@ import { describe, it, expect } from 'vitest'; import { formatNumberWithCurrency } from './index'; +import { Locale } from './formatNumberWithCurrency.types'; describe('formatNumberWithCurrency', () => { describe('기본 동작', () => { @@ -78,40 +79,44 @@ describe('formatNumberWithCurrency', () => { ).toBe('$1000'); }); - it('locale 옵션으로 통화 기호를 자동 적용해야 합니다.', () => { + it('decimal 옵션을 기반으로 소숫점 자리수를 포맷팅해야 합니다.', () => { expect( - formatNumberWithCurrency(1000, { - locale: 'USD', + formatNumberWithCurrency(1000.234, { + symbol: '$', + position: 'prefix', + decimal: 3, }) - ).toBe('$1,000'); + ).toBe('$1,000.234'); expect( - formatNumberWithCurrency(1000, { - locale: 'KRW', + formatNumberWithCurrency(1000.23, { + symbol: '$', + position: 'prefix', + decimal: 0, }) - ).toBe('1,000원'); + ).toBe('$1,000'); }); - it('locale 옵션이 있으면 commas 옵션을 제외한 나머지 옵션들은 무시되어야 합니다.', () => { + it('locale 옵션이 있으면 locale 옵션에 따라 통화 기호가 적용되어야 합니다.', () => { expect( formatNumberWithCurrency(1000, { - locale: 'USD', - commas: true, - symbol: '*', // 무시 - position: 'prefix', // 무시 - space: true, // 무시 + locale: 'en-US', // { symbol: '$', position: 'prefix', space: false, commas: true } }) ).toBe('$1,000'); expect( formatNumberWithCurrency(1000, { - locale: 'USD', - commas: false, - symbol: '*', // 무시 - position: 'prefix', // 무시 - space: true, // 무시 + locale: 'ko-KR', // { symbol: '₩', position: 'prefix', space: false, commas: true } }) - ).toBe('$1000'); + ).toBe('₩1,000'); + + // 소숫점 자리수 포맷팅 + expect( + formatNumberWithCurrency(1000.123, { + locale: 'en-US', // { symbol: '$', position: 'prefix', space: false, commas: true } + decimal: 2, + }) + ).toBe('$1,000.12'); }); }); @@ -122,10 +127,16 @@ describe('formatNumberWithCurrency', () => { ); }); + it('decimal이 0 이상의 정수가 아닌 경우 에러를 던져야 합니다.', () => { + expect(() => formatNumberWithCurrency(1000, { decimal: -1 })).toThrow( + 'decimal은 0 이상의 정수여야 합니다.' + ); + }); + it('지원하지 않는 locale 입력시 에러를 던져야 합니다.', () => { expect(() => formatNumberWithCurrency(1000, { - locale: 'INVALID' as unknown as 'KRW', + locale: 'INVALID' as unknown as Locale, }) ).toThrow('유효하지 않은 locale 입니다.'); }); diff --git a/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.types.ts b/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.types.ts index 581b1e372..8cb4666ed 100644 --- a/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.types.ts +++ b/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.types.ts @@ -1,4 +1,6 @@ -type Locale = 'KRW' | 'KRW_SYMBOL' | 'USD' | 'JPY' | 'CNY' | 'EUR'; +import { LOCALE_CURRENCY_MAP } from './formatNumberWithCurrency.constants'; + +export type Locale = keyof typeof LOCALE_CURRENCY_MAP; export interface FormatNumberCurrencyOptions { symbol?: string; @@ -6,4 +8,5 @@ export interface FormatNumberCurrencyOptions { space?: boolean; commas?: boolean; locale?: Locale; + decimal?: number; } diff --git a/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.utils.ts b/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.utils.ts index b6b94707d..732d65a2c 100644 --- a/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.utils.ts +++ b/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.utils.ts @@ -1,59 +1,29 @@ import { formatNumberWithCommas } from '../../formatter/formatNumberWithCommas'; import { FormatNumberCurrencyOptions } from './formatNumberWithCurrency.types'; -const LOCALE_CURRENCY_MAP = { - KRW: { symbol: '원', position: 'suffix', space: false }, - KRW_SYMBOL: { symbol: '₩', position: 'suffix', space: false }, - USD: { symbol: '$', position: 'prefix', space: false }, - JPY: { symbol: '¥', position: 'prefix', space: false }, - CNY: { symbol: '¥', position: 'prefix', space: false }, - EUR: { symbol: '€', position: 'prefix', space: false }, -} as const; - -/** - * @description 통화 옵션을 가져오는 함수 - * - * @param {Omit} options - 통화 옵션 - * @returns {Omit} locale을 제외한 통화 옵션 - */ -const getCurrencyOption = ( - options: Omit -): Omit => { - const { symbol, position, space, locale } = options; - - if (locale) { - if (!LOCALE_CURRENCY_MAP[locale]) { - throw new Error('유효하지 않은 locale 입니다.'); - } - - return LOCALE_CURRENCY_MAP[locale]; - } - - return { symbol, position, space }; -}; - /** * @description 숫자에 통화 기호를 추가하는 함수입니다. * * @param {number | string} value - 통화 기호를 추가할 숫자 또는 문자열 - * @param {FormatNumberCurrencyOptions & { isNegative: boolean }} currencyOption - 통화 단위 옵션 - * @param {string} [currencyOption.symbol=''] - 통화 기호 - * @param {'prefix' | 'suffix'} [currencyOption.position='suffix'] - 통화 기호 위치 - * @param {boolean} [currencyOption.space=false] - 숫자와 통화 기호 사이 공백 여부 + * @param {FormatNumberCurrencyOptions & { isNegative: boolean }} options - 통화 단위 옵션 + * @param {string} [options.symbol=''] - 통화 기호 + * @param {'prefix' | 'suffix'} [options.position='suffix'] - 통화 기호 위치 + * @param {boolean} [options.space=false] - 숫자와 통화 기호 사이 공백 여부 * @returns {string} 통화 기호가 추가된 문자열 */ export const getFormattedNumberWithCurrency = ( - value: number, - options: FormatNumberCurrencyOptions & { isNegative: boolean } + value: string, + options: Omit & { + isNegative: boolean; + } ): string => { - const { commas, ...restOption } = options; - const { symbol, position, space } = getCurrencyOption(restOption); + const { symbol, position, space, commas, isNegative } = options; const valueToUse = commas ? formatNumberWithCommas(value) : String(value); if (position === 'prefix') { // 음수 처리 - if (options.isNegative) { + if (isNegative) { const numericPart = valueToUse.slice(1); return '-' + symbol + (space ? ' ' : '') + numericPart; } diff --git a/packages/utils/src/formatter/formatNumberWithCurrency/index.ts b/packages/utils/src/formatter/formatNumberWithCurrency/index.ts index 7b7db37e2..492d8dd7d 100644 --- a/packages/utils/src/formatter/formatNumberWithCurrency/index.ts +++ b/packages/utils/src/formatter/formatNumberWithCurrency/index.ts @@ -1,7 +1,97 @@ import { isNumber } from '../../validator/isNumber'; -import { FormatNumberCurrencyOptions } from './formatNumberWithCurrency.types'; +import { LOCALE_CURRENCY_MAP } from './formatNumberWithCurrency.constants'; +import { + FormatNumberCurrencyOptions, + Locale, +} from './formatNumberWithCurrency.types'; import { getFormattedNumberWithCurrency } from './formatNumberWithCurrency.utils'; +/** + * @description `숫자 혹은 숫자로 이뤄진 문자열`을 주어진 `통화 기호`를 추가하는 함수입니다. + * + * 옵션이 없으면 기본값을 바탕으로 포맷팅됩니다. + * (기본 값: symbol: '', position: 'suffix', space: false, commas: true, decimal: 0) + * + * @param {number | string} value - 포맷팅할 숫자 값 + * @returns {string} 통화 기호가 포함된 포맷팅된 문자열 + * + * @example + * // 기본 사용법 + * formatNumberWithCurrency(1000) // '1,000' + * formatNumberWithCurrency(-1000) // '-1,000' + */ +export function formatNumberWithCurrency(value: number | string): string; + +/** + * @description `숫자 혹은 숫자로 이뤄진 문자열`을 주어진 `통화 기호`를 추가하는 함수입니다. + * + * `locale` 옵션을 제외한, `기본 옵션`이 주어지면 주어진 옵션에 따라 포맷팅됩니다. + * (기본 옵션: `symbol`, `position`, `space`, `commas`, `decimal`) + * + * @param {number | string} value - 포맷팅할 숫자 값 + * @param {Omit} options - 포맷팅 옵션 + * @param {string} [options.symbol=''] - 통화 기호 + * @param {'prefix' | 'suffix'} [options.position='suffix'] - 통화 기호 위치 + * @param {boolean} [options.space=false] - 숫자와 통화 기호 사이 공백 여부 + * @param {boolean} [options.commas=true] - 천의 단위 구분 여부 + * @param {number} [options.decimal=0] - 소숫점 자리수 + * @returns {string} 통화 기호가 포함된 포맷팅된 문자열 + * + * @example + * // 통화 기호(symbol) + * formatNumberWithCurrency(1000, { symbol: '원' }) // '1,000원' + * + * @example + * // 통화 기호 위치(position) + * formatNumberWithCurrency(1000, { symbol: '$', position: 'prefix' }) // '$1,000' + * formatNumberWithCurrency(-1000, { symbol: '$', position: 'prefix' }) // '-$1,000', 음수 + * + * @example + * // 기호와 숫자 사이 공백(space) + * formatNumberWithCurrency(1000, { symbol: '원', space: true }) // '1,000 원' + * + * @example + * // 천의 단위 구분 여부(commas) + * formatNumberWithCurrency(1000, { symbol: '원', commas: false }) // '1000원' + * formatNumberWithCurrency(1000, { symbol: '원', commas: true }) // '1,000원' + * + * @example + * // 소숫점 자리수 포맷팅 (기본값: 0) + * formatNumberWithCurrency(1000.234, { symbol: '원', decimal: 3 }) // '1,000.234원' + * formatNumberWithCurrency(1000.234, { symbol: '원', decimal: 0 }) // '1,000원' + */ +export function formatNumberWithCurrency( + value: number | string, + options: Omit +): string; + +/** + * @description `숫자 혹은 숫자로 이뤄진 문자열`을 주어진 `통화 기호`를 추가하는 함수입니다. + * + * `locale` 옵션이 있으면 `locale` 형식에 따라 포맷팅됩니다. `소수점 자리(decimal)` 옵션은 포함됩니다. + * + * @param {number | string} value - 포맷팅할 숫자 값 + * @param {{ locale: Locale }} options - 포맷팅 옵션 + * @param {Locale} [options.locale] - 통화 단위 + * @param {number} [options.decimal=0] - 소숫점 자리수 + * @returns {string} 통화 기호가 포함된 포맷팅된 문자열 + * + * @example + * // locale 옵션 적용 + * formatNumberWithCurrency(1000, { locale: 'en-US' }) // '$1,000' + * formatNumberWithCurrency(1000, { locale: 'ko-KR' }) // '₩1,000' + * formatNumberWithCurrency(1000, { locale: 'ja-JP' }) // '¥1,000' + * + * @example + * // 소숫점 자리수 포맷팅 + * formatNumberWithCurrency(1000.234, { locale: 'en-US', decimal: 3 }) // '$1,000.234' + * formatNumberWithCurrency(1000.234, { locale: 'en-US', decimal: 0 }) // '$1,000' + */ +export function formatNumberWithCurrency( + value: number | string, + options: { locale: Locale; decimal?: number } +): string; + /** * @description `숫자 혹은 숫자로 이뤄진 문자열`을 주어진 `통화 기호`를 추가하는 함수입니다. * @@ -11,8 +101,9 @@ import { getFormattedNumberWithCurrency } from './formatNumberWithCurrency.utils * @param {'prefix' | 'suffix'} [options.position='suffix'] - 통화 기호 위치 * @param {boolean} [options.space=false] - 숫자와 통화 기호 사이 공백 여부 * @param {boolean} [options.commas=true] - 천의 단위 구분 여부 - * @param {'KRW' | 'KRW_SYMBOL' | 'USD' | 'JPY' | 'CNY' | 'EUR'} [options.locale] - 통화 단위 - * @returns 통화 기호가 포함된 포맷팅된 문자열 + * @param {Locale} [options.locale] - 통화 단위 + * @param {number} [options.decimal=0] - 소숫점 자리수 + * @returns {string} 통화 기호가 포함된 포맷팅된 문자열 * * @example * // 기본 사용법 @@ -32,45 +123,64 @@ import { getFormattedNumberWithCurrency } from './formatNumberWithCurrency.utils * formatNumberWithCurrency(1000, { symbol: '$', position: 'prefix' }) // '$1,000' * * // 공백 추가 (기본값: false) - * formatNumberWithCurrency(1000, { symbol: '₩', space: true }) // '1,000 원' + * formatNumberWithCurrency(1000, { symbol: '원', space: true }) // '1,000 원' * * // 천의 단위 구분 여부 (기본값: true) * formatNumberWithCurrency(1000, { symbol: '원', commas: false }) // '1000원' * formatNumberWithCurrency(1000, { symbol: '원', commas: true }) // '1,000원' * - * // locale 사용 - * formatNumberWithCurrency(1000, { locale: 'USD' }) // '$1,000' - * formatNumberWithCurrency(1000, { locale: 'KRW' }) // '1,000원' + * // 소숫점 자리수 포맷팅 (기본값: 0) + * formatNumberWithCurrency(1000.234, { symbol: '원', decimal: 3 }) // '1,000.234원' + * formatNumberWithCurrency(1000.234, { symbol: '원', decimal: 0 }) // '1,000원' * - * // locale 옵션이 있으면 commas 옵션을 제외한 나머지 옵션들은 무시됩니다. - * formatNumberWithCurrency(1000, { locale: 'KRW', commas: false }) // '1000원' + * @example + * // locale 옵션 적용 + * // locale 옵션이 있으면 그 외 옵션들은 무시됩니다. + * formatNumberWithCurrency(1000, { locale: 'en-US' }) // '$1,000' + * formatNumberWithCurrency(1000, { locale: 'ko-KR' }) // '₩1,000' + * formatNumberWithCurrency(1000, { locale: 'ko-KR-UNIT' }) // '1,000원' */ export function formatNumberWithCurrency( value: number | string, options: FormatNumberCurrencyOptions = {} -) { +): string { const { symbol = '', position = 'suffix', space = false, commas = true, + decimal = 0, locale, } = options; const valueToUse = isNumber(value) ? value : Number(value); const isNegative = valueToUse < 0; + // 에러 처리 if (isNaN(valueToUse)) { throw new Error('value는 숫자 혹은 숫자로 이뤄진 문자열이여야 합니다.'); } + if (!Number.isInteger(decimal) || decimal < 0) { + throw new Error('decimal은 0 이상의 정수여야 합니다.'); + } - const formattedResult = getFormattedNumberWithCurrency(valueToUse, { + // locale 옵션 처리 + if (locale) { + if (!LOCALE_CURRENCY_MAP[locale]) { + throw new Error('유효하지 않은 locale 입니다.'); + } + + return valueToUse.toLocaleString(locale, { + style: 'currency', + currency: LOCALE_CURRENCY_MAP[locale].currency, + maximumFractionDigits: decimal, + }); + } + + return getFormattedNumberWithCurrency(valueToUse.toFixed(decimal), { symbol, position, space, - locale, commas, isNegative, }); - - return formattedResult; } diff --git a/packages/utils/src/formatter/formatNumberWithUnits/formatNumberWithUnits.utils.ts b/packages/utils/src/formatter/formatNumberWithUnits/formatNumberWithUnits.utils.ts index cdad89803..46dce4c79 100644 --- a/packages/utils/src/formatter/formatNumberWithUnits/formatNumberWithUnits.utils.ts +++ b/packages/utils/src/formatter/formatNumberWithUnits/formatNumberWithUnits.utils.ts @@ -1,8 +1,5 @@ import { formatNumberWithCommas } from '../../formatter/formatNumberWithCommas'; -import { - FormatNumberWithUnitsOptions, - Unit, -} from './formatNumberWithUnits.types'; +import { FormatNumberWithUnitsOptions } from './formatNumberWithUnits.types'; /** * @description 쉼표 사용 여부에 따라 숫자를 포맷팅하는 함수 @@ -22,8 +19,7 @@ const getNumberWithConditionalCommas = ( * @description 주어진 단위(units)에 따라 숫자를 포맷팅하는 함수 * * @param {number} value - 포맷팅할 숫자 값 - * @param {Unit[] | readonly Unit[]} units - 변환할 단위 배열 - * @param {Omit, 'units'>} options - 포맷팅 옵션 + * @param {Required} options - 포맷팅 옵션 * @param {boolean} options.commas - 천 단위 구분 쉼표 사용 여부입니다. * @param {boolean} options.space - 단위 사이 공백 추가 여부입니다. * @param {number} options.decimal - 소수점 자릿수입니다. @@ -31,10 +27,9 @@ const getNumberWithConditionalCommas = ( */ export const getFormattedValueWithUnits = ( value: number, - units: Unit[] | readonly Unit[], - options: Omit, 'units'> + options: Required ): string => { - const { commas, space, decimal, floorUnit } = options; + const { units, commas, space, decimal, floorUnit } = options; const absoluteValue = Math.abs(value); const isNegative = value < 0; diff --git a/packages/utils/src/formatter/formatNumberWithUnits/index.ts b/packages/utils/src/formatter/formatNumberWithUnits/index.ts index 2c9b82f7e..22f442fda 100644 --- a/packages/utils/src/formatter/formatNumberWithUnits/index.ts +++ b/packages/utils/src/formatter/formatNumberWithUnits/index.ts @@ -66,8 +66,8 @@ export function formatNumberWithUnits( // value 값을 기준으로 내림차순 정렬 const sortedUnits = [...units].sort((a, b) => b.value - a.value); - const valueToUse = isNumber(value) ? value : Number(value); + // 에러 처리 if (isNaN(valueToUse)) { throw new Error('value는 숫자 혹은 숫자로 이뤄진 문자열이여야 합니다.'); @@ -86,12 +86,11 @@ export function formatNumberWithUnits( throw new Error('decimal은 0 이상의 정수여야 합니다.'); } - const formattedResult = getFormattedValueWithUnits(valueToUse, sortedUnits, { + return getFormattedValueWithUnits(valueToUse, { + units: sortedUnits, commas, space, decimal, floorUnit, }); - - return formattedResult; }