From 3b22847e993010d5ec2f3c244ff704479a853105 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: Mon, 13 Jan 2025 00:26:49 +0900 Subject: [PATCH] =?UTF-8?q?fix(utils):=20formatNumberWithCurrency=20decima?= =?UTF-8?q?l=20=EC=98=B5=EC=85=98=20=EC=A0=9C=EA=B1=B0=20(#673)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../formatter/formatNumberWithCurrency.md | 43 ++++++++--------- .../formatNumberWithCurrency.spec.ts | 48 ++++++++----------- .../formatNumberWithCurrency.types.ts | 1 - .../formatNumberWithCurrency.utils.ts | 4 +- .../formatNumberWithCurrency/index.ts | 39 +++++---------- 5 files changed, 53 insertions(+), 82 deletions(-) diff --git a/docs/docs/utils/formatter/formatNumberWithCurrency.md b/docs/docs/utils/formatter/formatNumberWithCurrency.md index c55b5abe..2cf3ad60 100644 --- a/docs/docs/utils/formatter/formatNumberWithCurrency.md +++ b/docs/docs/utils/formatter/formatNumberWithCurrency.md @@ -3,10 +3,10 @@ `숫자` 혹은 `숫자로 이루어진 문자열`을 주어진 `통화 기호`를 추가하는 함수입니다. 기본 옵션으로 직접 원하는 형태로 숫자에 통화 기호를 추가해 포맷팅할 수 있습니다. -- 기본 옵션: `symbol`, `position`, `space`, `commas`, `decimal` +- 기본 옵션: `symbol`, `position`, `space`, `commas` -`locale` 옵션이 있으면 `locale` 형식에 따라 포맷팅됩니다. `소수점 자리(decimal)` 옵션은 포함됩니다. -- `locale`, `decimal` 옵션을 제외한 나머지 옵션들은 무시됩니다. +`locale` 옵션이 있으면 `locale` 형식에 따라 포맷팅됩니다. +- `locale` 옵션을 제외한 나머지 옵션들은 무시됩니다.
@@ -20,7 +20,6 @@ interface FormatNumberCurrencyOptions { position?: 'prefix' | 'suffix'; // default: 'suffix' space?: boolean; // default: false commas?: boolean; // default: true - decimal?: number; // default: 0 locale?: Locale; } ``` @@ -29,7 +28,7 @@ interface FormatNumberCurrencyOptions { function formatNumberWithCurrency(value: number | string): string; // locale 옵션을 제외한, 기본 옵션이 주어지면 주어진 옵션에 따라 포맷팅됩니다. -// (기본 옵션: `symbol`, `position`, `space`, `commas`, `decimal`) +// (기본 옵션: `symbol`, `position`, `space`, `commas`) function formatNumberWithCurrency( value: number | string, options: Omit @@ -38,7 +37,7 @@ function formatNumberWithCurrency( // locale 옵션이 있으면 locale 형식에 따라 포맷팅됩니다. function formatNumberWithCurrency( value: number | string, - options: { locale: Locale; decimal?: number } + options: { locale: Locale } ): string; ``` @@ -49,27 +48,25 @@ import { formatNumberWithCurrency } from '@modern-kit/utils'; // 기본 동작 formatNumberWithCurrency(1000) // '1,000' - -// 통화 기호 추가 (기본 값: '') -formatNumberWithCurrency(1000, { symbol: '원' }) // '1,000원' -formatNumberWithCurrency(1000, { symbol: '$', position: 'prefix' }) // '$1,000' +formatNumberWithCurrency(-1000) // '-1,000' +formatNumberWithCurrency(1000.123) // '1,000.123' // 숫자로 이루어진 문자열도 허용 -formatNumberWithCurrency('1000', { symbol: '원' }) // '1,000원' -formatNumberWithCurrency('1000', { symbol: '$', position: 'prefix' }) // '$1,000' - -// 음수 처리 -formatNumberWithCurrency(-1000, { symbol: '$', position: 'prefix' }) // '-$1,000' -formatNumberWithCurrency(-1000, { symbol: '원', position: 'suffix' }) // '-1,000원' +formatNumberWithCurrency('1000') // '1,000' +formatNumberWithCurrency('-1000') // '-1,000' +formatNumberWithCurrency('1000.123') // '1,000.123' ```
### 옵션 사용 -- 기본 옵션 사용(`symbol`, `position`, `space`, `commas`, `decimal`) +- 기본 옵션 사용(`symbol`, `position`, `space`, `commas`) ```ts title="typescript" import { formatNumberWithCurrency } from '@modern-kit/utils'; +// 통화 기호 추가 (기본 값: '') +formatNumberWithCurrency(1000, { symbol: '원' }) // '1,000원' + // 통호 기호 위치 변경 (기본값: 'suffix') formatNumberWithCurrency(1000, { symbol: '$', position: 'prefix' }) // '$1,000' @@ -80,10 +77,6 @@ formatNumberWithCurrency(1000, { symbol: '$', position: 'prefix', space: true }) // 천의 단위 구분 여부 (기본값: true) formatNumberWithCurrency(1000, { symbol: '원', commas: false }) // '1000원' formatNumberWithCurrency(1000, { symbol: '원', commas: true }) // '1,000원' - -// 소숫점 자리수 포맷팅 (기본값: 0) -formatNumberWithCurrency(1000.234, { symbol: '원', decimal: 3 }) // '1,000.234원' -formatNumberWithCurrency(1000.234, { symbol: '원', decimal: 0 }) // '1,000원' ```
@@ -102,7 +95,9 @@ 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' +// 음수 처리 +formatNumberWithCurrency(-1000, { locale: 'ko-KR' }) // '-₩1,000' + +// 소숫점 처리 +formatNumberWithCurrency(1000.234, { locale: 'en-US' }) // '$1,000.234' ``` diff --git a/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.spec.ts b/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.spec.ts index cc4565d3..351b88db 100644 --- a/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.spec.ts +++ b/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.spec.ts @@ -4,16 +4,25 @@ import { Locale } from './formatNumberWithCurrency.types'; describe('formatNumberWithCurrency', () => { describe('기본 동작', () => { - it('옵션 없이 호출하면 숫자만 반환해야 합니다.', () => { + it('옵션 없이 호출하면 기본 옵션으로 포맷팅되어야 합니다.', () => { expect(formatNumberWithCurrency(1000)).toBe('1,000'); - expect(formatNumberWithCurrency('1000')).toBe('1,000'); + expect(formatNumberWithCurrency(1000.123)).toBe('1,000.123'); }); it('기본적으로 접미사(suffix) 위치에 통화 기호를 추가해야 합니다.', () => { expect(formatNumberWithCurrency(1000, { symbol: '원' })).toBe('1,000원'); + expect(formatNumberWithCurrency(1000.123, { symbol: '원' })).toBe( + '1,000.123원' + ); + }); + + it('숫자로 이뤄진 문자열도 정상적으로 포맷팅되어야 합니다.', () => { expect(formatNumberWithCurrency('1000', { symbol: '원' })).toBe( '1,000원' ); + expect(formatNumberWithCurrency('1000.123', { symbol: '원' })).toBe( + '1,000.123원' + ); // 소수 }); it('음수일 때 통화 기호를 앞에 추가해야 합니다.', () => { @@ -79,24 +88,6 @@ describe('formatNumberWithCurrency', () => { ).toBe('$1000'); }); - it('decimal 옵션을 기반으로 소숫점 자리수를 포맷팅해야 합니다.', () => { - expect( - formatNumberWithCurrency(1000.234, { - symbol: '$', - position: 'prefix', - decimal: 3, - }) - ).toBe('$1,000.234'); - - expect( - formatNumberWithCurrency(1000.23, { - symbol: '$', - position: 'prefix', - decimal: 0, - }) - ).toBe('$1,000'); - }); - it('locale 옵션이 있으면 locale 옵션에 따라 통화 기호가 적용되어야 합니다.', () => { expect( formatNumberWithCurrency(1000, { @@ -110,13 +101,18 @@ describe('formatNumberWithCurrency', () => { }) ).toBe('₩1,000'); - // 소숫점 자리수 포맷팅 + expect( + formatNumberWithCurrency(-1000, { + locale: 'ko-KR', // { symbol: '₩', position: 'prefix', space: false, commas: true } + }) + ).toBe('-₩1,000'); + + // 소수점 처리 expect( formatNumberWithCurrency(1000.123, { locale: 'en-US', // { symbol: '$', position: 'prefix', space: false, commas: true } - decimal: 2, }) - ).toBe('$1,000.12'); + ).toBe('$1,000.123'); }); }); @@ -127,12 +123,6 @@ describe('formatNumberWithCurrency', () => { ); }); - it('decimal이 0 이상의 정수가 아닌 경우 에러를 던져야 합니다.', () => { - expect(() => formatNumberWithCurrency(1000, { decimal: -1 })).toThrow( - 'decimal은 0 이상의 정수여야 합니다.' - ); - }); - it('지원하지 않는 locale 입력시 에러를 던져야 합니다.', () => { expect(() => formatNumberWithCurrency(1000, { diff --git a/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.types.ts b/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.types.ts index 8cb4666e..82cf2a47 100644 --- a/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.types.ts +++ b/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.types.ts @@ -8,5 +8,4 @@ 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 732d65a2..608b32ef 100644 --- a/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.utils.ts +++ b/packages/utils/src/formatter/formatNumberWithCurrency/formatNumberWithCurrency.utils.ts @@ -12,8 +12,8 @@ import { FormatNumberCurrencyOptions } from './formatNumberWithCurrency.types'; * @returns {string} 통화 기호가 추가된 문자열 */ export const getFormattedNumberWithCurrency = ( - value: string, - options: Omit & { + value: number, + options: FormatNumberCurrencyOptions & { isNegative: boolean; } ): string => { diff --git a/packages/utils/src/formatter/formatNumberWithCurrency/index.ts b/packages/utils/src/formatter/formatNumberWithCurrency/index.ts index 492d8dd7..b289e522 100644 --- a/packages/utils/src/formatter/formatNumberWithCurrency/index.ts +++ b/packages/utils/src/formatter/formatNumberWithCurrency/index.ts @@ -10,7 +10,7 @@ import { getFormattedNumberWithCurrency } from './formatNumberWithCurrency.utils * @description `숫자 혹은 숫자로 이뤄진 문자열`을 주어진 `통화 기호`를 추가하는 함수입니다. * * 옵션이 없으면 기본값을 바탕으로 포맷팅됩니다. - * (기본 값: symbol: '', position: 'suffix', space: false, commas: true, decimal: 0) + * (기본 값: symbol: '', position: 'suffix', space: false, commas: true) * * @param {number | string} value - 포맷팅할 숫자 값 * @returns {string} 통화 기호가 포함된 포맷팅된 문자열 @@ -26,7 +26,7 @@ export function formatNumberWithCurrency(value: number | string): string; * @description `숫자 혹은 숫자로 이뤄진 문자열`을 주어진 `통화 기호`를 추가하는 함수입니다. * * `locale` 옵션을 제외한, `기본 옵션`이 주어지면 주어진 옵션에 따라 포맷팅됩니다. - * (기본 옵션: `symbol`, `position`, `space`, `commas`, `decimal`) + * (기본 옵션: `symbol`, `position`, `space`, `commas`) * * @param {number | string} value - 포맷팅할 숫자 값 * @param {Omit} options - 포맷팅 옵션 @@ -34,17 +34,17 @@ export function formatNumberWithCurrency(value: number | string): string; * @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원' + * formatNumberWithCurrency(1000.123, { symbol: '원' }) // '1,000.123원' + * formatNumberWithCurrency(-1000, { symbol: '원' }) // '-1,000.123원' * * @example * // 통화 기호 위치(position) * formatNumberWithCurrency(1000, { symbol: '$', position: 'prefix' }) // '$1,000' - * formatNumberWithCurrency(-1000, { symbol: '$', position: 'prefix' }) // '-$1,000', 음수 * * @example * // 기호와 숫자 사이 공백(space) @@ -55,10 +55,6 @@ export function formatNumberWithCurrency(value: number | string): string; * 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, @@ -68,12 +64,11 @@ export function formatNumberWithCurrency( /** * @description `숫자 혹은 숫자로 이뤄진 문자열`을 주어진 `통화 기호`를 추가하는 함수입니다. * - * `locale` 옵션이 있으면 `locale` 형식에 따라 포맷팅됩니다. `소수점 자리(decimal)` 옵션은 포함됩니다. + * `locale` 옵션이 있으면 `locale` 형식에 따라 포맷팅됩니다. * * @param {number | string} value - 포맷팅할 숫자 값 * @param {{ locale: Locale }} options - 포맷팅 옵션 * @param {Locale} [options.locale] - 통화 단위 - * @param {number} [options.decimal=0] - 소숫점 자리수 * @returns {string} 통화 기호가 포함된 포맷팅된 문자열 * * @example @@ -82,14 +77,14 @@ export function formatNumberWithCurrency( * 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' + * // 소수점 처리 + * formatNumberWithCurrency(1000.123, { locale: 'en-US' }) // '$1,000.123' + * formatNumberWithCurrency(1000.123, { locale: 'ko-KR' }) // '₩1,000.123' + * formatNumberWithCurrency(1000.123, { locale: 'ja-JP' }) // '¥1,000.123' */ export function formatNumberWithCurrency( value: number | string, - options: { locale: Locale; decimal?: number } + options: { locale: Locale } ): string; /** @@ -102,7 +97,6 @@ export function formatNumberWithCurrency( * @param {boolean} [options.space=false] - 숫자와 통화 기호 사이 공백 여부 * @param {boolean} [options.commas=true] - 천의 단위 구분 여부 * @param {Locale} [options.locale] - 통화 단위 - * @param {number} [options.decimal=0] - 소숫점 자리수 * @returns {string} 통화 기호가 포함된 포맷팅된 문자열 * * @example @@ -129,10 +123,6 @@ export function formatNumberWithCurrency( * formatNumberWithCurrency(1000, { symbol: '원', commas: false }) // '1000원' * formatNumberWithCurrency(1000, { symbol: '원', commas: true }) // '1,000원' * - * // 소숫점 자리수 포맷팅 (기본값: 0) - * formatNumberWithCurrency(1000.234, { symbol: '원', decimal: 3 }) // '1,000.234원' - * formatNumberWithCurrency(1000.234, { symbol: '원', decimal: 0 }) // '1,000원' - * * @example * // locale 옵션 적용 * // locale 옵션이 있으면 그 외 옵션들은 무시됩니다. @@ -149,7 +139,6 @@ export function formatNumberWithCurrency( position = 'suffix', space = false, commas = true, - decimal = 0, locale, } = options; const valueToUse = isNumber(value) ? value : Number(value); @@ -159,9 +148,6 @@ export function formatNumberWithCurrency( if (isNaN(valueToUse)) { throw new Error('value는 숫자 혹은 숫자로 이뤄진 문자열이여야 합니다.'); } - if (!Number.isInteger(decimal) || decimal < 0) { - throw new Error('decimal은 0 이상의 정수여야 합니다.'); - } // locale 옵션 처리 if (locale) { @@ -172,11 +158,12 @@ export function formatNumberWithCurrency( return valueToUse.toLocaleString(locale, { style: 'currency', currency: LOCALE_CURRENCY_MAP[locale].currency, - maximumFractionDigits: decimal, + minimumFractionDigits: 0, + maximumFractionDigits: 20, }); } - return getFormattedNumberWithCurrency(valueToUse.toFixed(decimal), { + return getFormattedNumberWithCurrency(valueToUse, { symbol, position, space,