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,