Skip to content

Commit

Permalink
fix(utils): formatNumberWithCurrency decimal 옵션 제거 (#673)
Browse files Browse the repository at this point in the history
  • Loading branch information
ssi02014 authored Jan 12, 2025
1 parent 37ef40a commit 3b22847
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 82 deletions.
43 changes: 19 additions & 24 deletions docs/docs/utils/formatter/formatNumberWithCurrency.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
`숫자` 혹은 `숫자로 이루어진 문자열`을 주어진 `통화 기호`를 추가하는 함수입니다.

기본 옵션으로 직접 원하는 형태로 숫자에 통화 기호를 추가해 포맷팅할 수 있습니다.
- 기본 옵션: `symbol`, `position`, `space`, `commas`, `decimal`
- 기본 옵션: `symbol`, `position`, `space`, `commas`

`locale` 옵션이 있으면 `locale` 형식에 따라 포맷팅됩니다. `소수점 자리(decimal)` 옵션은 포함됩니다.
- `locale`, `decimal` 옵션을 제외한 나머지 옵션들은 무시됩니다.
`locale` 옵션이 있으면 `locale` 형식에 따라 포맷팅됩니다.
- `locale` 옵션을 제외한 나머지 옵션들은 무시됩니다.

<br />

Expand All @@ -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;
}
```
Expand All @@ -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<FormatNumberCurrencyOptions, 'locale'>
Expand All @@ -38,7 +37,7 @@ function formatNumberWithCurrency(
// locale 옵션이 있으면 locale 형식에 따라 포맷팅됩니다.
function formatNumberWithCurrency(
value: number | string,
options: { locale: Locale; decimal?: number }
options: { locale: Locale }
): string;
```

Expand All @@ -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'
```

<br />

### 옵션 사용
- 기본 옵션 사용(`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'

Expand All @@ -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원'
```

<br />
Expand All @@ -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'
```
Original file line number Diff line number Diff line change
Expand Up @@ -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('음수일 때 통화 기호를 앞에 추가해야 합니다.', () => {
Expand Down Expand Up @@ -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, {
Expand All @@ -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');
});
});

Expand All @@ -127,12 +123,6 @@ describe('formatNumberWithCurrency', () => {
);
});

it('decimal이 0 이상의 정수가 아닌 경우 에러를 던져야 합니다.', () => {
expect(() => formatNumberWithCurrency(1000, { decimal: -1 })).toThrow(
'decimal은 0 이상의 정수여야 합니다.'
);
});

it('지원하지 않는 locale 입력시 에러를 던져야 합니다.', () => {
expect(() =>
formatNumberWithCurrency(1000, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@ export interface FormatNumberCurrencyOptions {
space?: boolean;
commas?: boolean;
locale?: Locale;
decimal?: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { FormatNumberCurrencyOptions } from './formatNumberWithCurrency.types';
* @returns {string} 통화 기호가 추가된 문자열
*/
export const getFormattedNumberWithCurrency = (
value: string,
options: Omit<FormatNumberCurrencyOptions, 'decimal'> & {
value: number,
options: FormatNumberCurrencyOptions & {
isNegative: boolean;
}
): string => {
Expand Down
39 changes: 13 additions & 26 deletions packages/utils/src/formatter/formatNumberWithCurrency/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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} 통화 기호가 포함된 포맷팅된 문자열
Expand All @@ -26,25 +26,25 @@ export function formatNumberWithCurrency(value: number | string): string;
* @description `숫자 혹은 숫자로 이뤄진 문자열`을 주어진 `통화 기호`를 추가하는 함수입니다.
*
* `locale` 옵션을 제외한, `기본 옵션`이 주어지면 주어진 옵션에 따라 포맷팅됩니다.
* (기본 옵션: `symbol`, `position`, `space`, `commas`, `decimal`)
* (기본 옵션: `symbol`, `position`, `space`, `commas`)
*
* @param {number | string} value - 포맷팅할 숫자 값
* @param {Omit<FormatNumberCurrencyOptions, 'locale'>} 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원'
* 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)
Expand All @@ -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,
Expand All @@ -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
Expand All @@ -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;

/**
Expand All @@ -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
Expand All @@ -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 옵션이 있으면 그 외 옵션들은 무시됩니다.
Expand All @@ -149,7 +139,6 @@ export function formatNumberWithCurrency(
position = 'suffix',
space = false,
commas = true,
decimal = 0,
locale,
} = options;
const valueToUse = isNumber(value) ? value : Number(value);
Expand All @@ -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) {
Expand All @@ -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,
Expand Down

0 comments on commit 3b22847

Please sign in to comment.