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;
}