Merge pull request #33133 from woocommerce/dev/33101-migrate-woo-currency-to-ts

Migrate `woocommerce/currency` to TS
This commit is contained in:
Chi-Hsuan Huang 2022-05-23 16:21:08 +08:00 committed by GitHub
commit 02a483dc32
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 119 additions and 52 deletions

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Migrate @woocommerce/currency to TS

View File

@ -19,6 +19,7 @@
}, },
"main": "build/index.js", "main": "build/index.js",
"module": "build-module/index.js", "module": "build-module/index.js",
"types": "build-types",
"react-native": "src/index", "react-native": "src/index",
"dependencies": { "dependencies": {
"@woocommerce/number": "workspace:*", "@woocommerce/number": "workspace:*",

View File

@ -4,7 +4,7 @@
import { createElement } from '@wordpress/element'; import { createElement } from '@wordpress/element';
import { decodeEntities } from '@wordpress/html-entities'; import { decodeEntities } from '@wordpress/html-entities';
import { sprintf } from '@wordpress/i18n'; import { sprintf } from '@wordpress/i18n';
import { numberFormat } from '@woocommerce/number'; import { NumberConfig, numberFormat } from '@woocommerce/number';
import deprecated from '@wordpress/deprecated'; import deprecated from '@wordpress/deprecated';
/** /**
@ -18,26 +18,106 @@ import deprecated from '@wordpress/deprecated';
* @typedef {NumberConfig & CurrencyProps} CurrencyConfig * @typedef {NumberConfig & CurrencyProps} CurrencyConfig
*/ */
export type SymbolPosition = 'left' | 'right' | 'left_space' | 'right_space';
export type CurrencyProps = {
code: string;
symbol: string;
symbolPosition: SymbolPosition;
priceFormat?: string;
};
export type CurrencyConfig = Partial< NumberConfig & CurrencyProps >;
export type Currency = {
code: string;
symbol: string;
symbolPosition: string;
decimalSeparator: string;
priceFormat: string;
thousandSeparator: string;
precision: number;
};
export type CountryInfo = {
// https://github.com/woocommerce/woocommerce/blob/trunk/plugins/woocommerce/i18n/locale-info.php#L15-L28
currency_code: string;
currency_pos: SymbolPosition;
thousand_sep: string;
decimal_sep: string;
num_decimals: number;
weight_unit: string;
dimension_unit: string;
direction: string;
default_locale: string;
name: string;
singular: string;
plural: string;
short_symbol: string;
locales: string[];
};
/** /**
* *
* @param {CurrencyConfig} currencySetting * @param {CurrencyConfig} currencySetting
* @return {Object} currency object * @return {Object} currency object
*/ */
const CurrencyFactory = function ( currencySetting ) { const CurrencyFactory = function ( currencySetting?: CurrencyConfig ) {
let currency; let currency: Currency;
setCurrency( currencySetting ); function stripTags( str: string ) {
const tmp = document.createElement( 'DIV' );
tmp.innerHTML = str;
return tmp.textContent || tmp.innerText || '';
}
function setCurrency( setting ) { /**
* Get the default price format from a currency.
*
* @param {CurrencyConfig} config Currency configuration.
* @return {string} Price format.
*/
function getPriceFormat( config: CurrencyConfig ) {
if ( config.priceFormat ) {
return stripTags( config.priceFormat.toString() );
}
switch ( config.symbolPosition ) {
case 'left':
return '%1$s%2$s';
case 'right':
return '%2$s%1$s';
case 'left_space':
return '%1$s %2$s';
case 'right_space':
return '%2$s %1$s';
}
return '%1$s%2$s';
}
function setCurrency( setting?: CurrencyConfig ) {
const defaultCurrency = { const defaultCurrency = {
code: 'USD', code: 'USD',
symbol: '$', symbol: '$',
symbolPosition: 'left', symbolPosition: 'left' as const,
thousandSeparator: ',', thousandSeparator: ',',
decimalSeparator: '.', decimalSeparator: '.',
precision: 2, precision: 2,
}; };
const config = { ...defaultCurrency, ...setting }; const config = { ...defaultCurrency, ...setting };
let precision = config.precision;
if ( precision === null ) {
// eslint-disable-next-line no-console
console.warn( 'Currency precision is null' );
// eslint-enable-next-line no-console
precision = NaN;
} else if ( typeof precision === 'string' ) {
precision = parseInt( precision, 10 );
}
currency = { currency = {
code: config.code.toString(), code: config.code.toString(),
symbol: config.symbol.toString(), symbol: config.symbol.toString(),
@ -45,16 +125,10 @@ const CurrencyFactory = function ( currencySetting ) {
decimalSeparator: config.decimalSeparator.toString(), decimalSeparator: config.decimalSeparator.toString(),
priceFormat: getPriceFormat( config ), priceFormat: getPriceFormat( config ),
thousandSeparator: config.thousandSeparator.toString(), thousandSeparator: config.thousandSeparator.toString(),
precision: parseInt( config.precision, 10 ), precision,
}; };
} }
function stripTags( str ) {
const tmp = document.createElement( 'DIV' );
tmp.innerHTML = str;
return tmp.textContent || tmp.innerText || '';
}
/** /**
* Formats money value. * Formats money value.
* *
@ -62,7 +136,7 @@ const CurrencyFactory = function ( currencySetting ) {
* @param {boolean} [useCode=false] Set to `true` to use the currency code instead of the symbol. * @param {boolean} [useCode=false] Set to `true` to use the currency code instead of the symbol.
* @return {?string} A formatted string. * @return {?string} A formatted string.
*/ */
function formatAmount( number, useCode = false ) { function formatAmount( number: number | string, useCode = false ) {
const formattedNumber = numberFormat( currency, number ); const formattedNumber = numberFormat( currency, number );
if ( formattedNumber === '' ) { if ( formattedNumber === '' ) {
@ -82,7 +156,7 @@ const CurrencyFactory = function ( currencySetting ) {
* @param {number|string} number number to format * @param {number|string} number number to format
* @return {?string} A formatted string. * @return {?string} A formatted string.
*/ */
function formatCurrency( number ) { function formatCurrency( number: number | string ) {
deprecated( 'Currency().formatCurrency', { deprecated( 'Currency().formatCurrency', {
version: '5.0.0', version: '5.0.0',
alternative: 'Currency().formatAmount', alternative: 'Currency().formatAmount',
@ -92,31 +166,6 @@ const CurrencyFactory = function ( currencySetting ) {
return formatAmount( number ); return formatAmount( number );
} }
/**
* Get the default price format from a currency.
*
* @param {CurrencyConfig} config Currency configuration.
* @return {string} Price format.
*/
function getPriceFormat( config ) {
if ( config.priceFormat ) {
return stripTags( config.priceFormat.toString() );
}
switch ( config.symbolPosition ) {
case 'left':
return '%1$s%2$s';
case 'right':
return '%2$s%1$s';
case 'left_space':
return '%1$s %2$s';
case 'right_space':
return '%2$s %1$s';
}
return '%1$s%2$s';
}
/** /**
* Get formatted data for a country from supplied locale and symbol info. * Get formatted data for a country from supplied locale and symbol info.
* *
@ -126,13 +175,16 @@ const CurrencyFactory = function ( currencySetting ) {
* @return {CurrencyConfig | {}} Formatted currency data for country. * @return {CurrencyConfig | {}} Formatted currency data for country.
*/ */
function getDataForCountry( function getDataForCountry(
countryCode, countryCode: string,
localeInfo = {}, localeInfo: Record< string, CountryInfo | undefined > = {},
currencySymbols = {} currencySymbols: Record< string, string | undefined > = {}
) { ): CurrencyConfig | Record< string, never > {
const countryInfo = localeInfo[ countryCode ] || {}; const countryInfo = localeInfo[ countryCode ];
const symbol = currencySymbols[ countryInfo.currency_code ]; if ( ! countryInfo ) {
return {};
}
const symbol = currencySymbols[ countryInfo.currency_code ];
if ( ! symbol ) { if ( ! symbol ) {
return {}; return {};
} }
@ -147,6 +199,8 @@ const CurrencyFactory = function ( currencySetting ) {
}; };
} }
setCurrency( currencySetting );
return { return {
getCurrencyConfig: () => { getCurrencyConfig: () => {
return { ...currency }; return { ...currency };
@ -164,7 +218,7 @@ const CurrencyFactory = function ( currencySetting ) {
* @param {number|string} number A floating point number (or integer), or string that converts to a number * @param {number|string} number A floating point number (or integer), or string that converts to a number
* @return {number} The original number rounded to a decimal point * @return {number} The original number rounded to a decimal point
*/ */
formatDecimal( number ) { formatDecimal( number: number | string ) {
if ( typeof number !== 'number' ) { if ( typeof number !== 'number' ) {
number = parseFloat( number ); number = parseFloat( number );
} }
@ -185,7 +239,7 @@ const CurrencyFactory = function ( currencySetting ) {
* @param {number|string} number A floating point number (or integer), or string that converts to a number * @param {number|string} number A floating point number (or integer), or string that converts to a number
* @return {string} The original number rounded to a decimal point * @return {string} The original number rounded to a decimal point
*/ */
formatDecimalString( number ) { formatDecimalString( number: number | string ) {
if ( typeof number !== 'number' ) { if ( typeof number !== 'number' ) {
number = parseFloat( number ); number = parseFloat( number );
} }
@ -202,7 +256,7 @@ const CurrencyFactory = function ( currencySetting ) {
* @param {number|string} number A floating point number (or integer), or string that converts to a number * @param {number|string} number A floating point number (or integer), or string that converts to a number
* @return {Node|string} The number formatted as currency and rendered for display. * @return {Node|string} The number formatted as currency and rendered for display.
*/ */
render( number ) { render( number: number | string ) {
if ( typeof number !== 'number' ) { if ( typeof number !== 'number' ) {
number = parseFloat( number ); number = parseFloat( number );
} }

View File

@ -1,7 +1,7 @@
/** /**
* Internal dependencies * Internal dependencies
*/ */
import Currency from '../'; import Currency from '..';
describe( 'formatAmount', () => { describe( 'formatAmount', () => {
it( 'should use defaults (USD) when currency not passed in', () => { it( 'should use defaults (USD) when currency not passed in', () => {
@ -37,7 +37,9 @@ describe( 'formatAmount', () => {
it( "should return empty string when given an input that isn't a number", () => { it( "should return empty string when given an input that isn't a number", () => {
const currency = Currency(); const currency = Currency();
expect( currency.formatAmount( 'abc' ) ).toBe( '' ); expect( currency.formatAmount( 'abc' ) ).toBe( '' );
// @ts-expect-error formatAccount expects a number or string;
expect( currency.formatAmount( false ) ).toBe( '' ); expect( currency.formatAmount( false ) ).toBe( '' );
// @ts-expect-error formatAccount expects a number or string;
expect( currency.formatAmount( null ) ).toBe( '' ); expect( currency.formatAmount( null ) ).toBe( '' );
} ); } );
} ); } );
@ -65,7 +67,9 @@ describe( 'currency.formatDecimal', () => {
it( "should return 0 when given an input that isn't a number", () => { it( "should return 0 when given an input that isn't a number", () => {
const currency = Currency(); const currency = Currency();
expect( currency.formatDecimal( 'abc' ) ).toBe( 0 ); expect( currency.formatDecimal( 'abc' ) ).toBe( 0 );
// @ts-expect-error formatAccount expects a number or string;
expect( currency.formatDecimal( false ) ).toBe( 0 ); expect( currency.formatDecimal( false ) ).toBe( 0 );
// @ts-expect-error formatAccount expects a number or string;
expect( currency.formatDecimal( null ) ).toBe( 0 ); expect( currency.formatDecimal( null ) ).toBe( 0 );
} ); } );
} ); } );
@ -93,7 +97,9 @@ describe( 'currency.formatDecimalString', () => {
it( "should return empty string when given an input that isn't a number", () => { it( "should return empty string when given an input that isn't a number", () => {
const currency = Currency(); const currency = Currency();
expect( currency.formatDecimalString( 'abc' ) ).toBe( '' ); expect( currency.formatDecimalString( 'abc' ) ).toBe( '' );
// @ts-expect-error formatAccount expects a number or string;
expect( currency.formatDecimalString( false ) ).toBe( '' ); expect( currency.formatDecimalString( false ) ).toBe( '' );
// @ts-expect-error formatAccount expects a number or string;
expect( currency.formatDecimalString( null ) ).toBe( '' ); expect( currency.formatDecimalString( null ) ).toBe( '' );
} ); } );
} ); } );

View File

@ -1,8 +1,10 @@
{ {
"extends": "../tsconfig", "extends": "../tsconfig",
"compilerOptions": { "compilerOptions": {
"declaration": true,
"rootDir": "src", "rootDir": "src",
"outDir": "build-module" "outDir": "build-module",
"declaration": true,
"declarationMap": true,
"declarationDir": "./build-types"
} }
} }