diff --git a/packages/morpho-ts/src/format/format/README.md b/packages/morpho-ts/src/format/format/README.md index 73faeb69..82a68a83 100644 --- a/packages/morpho-ts/src/format/format/README.md +++ b/packages/morpho-ts/src/format/format/README.md @@ -23,7 +23,7 @@ The `format` object provides access to different formatters: ### Usage Each formatter can be accessed through the `format` object and provides chainable methods to customize the output. The formatted value can be obtained calling `.of(value)` for `number` or `.of(value, decimals)` for `bigint`. -The return value will retain the nullability of the input value, unless a `.default()` method is applied (refer to [Number Formatter](#2-number-formatter) for details). +The return value will retain the nullability of the input value (giving priority to `value` over `decimals` for bigints, if none is defined), unless a `.default()` method is applied (refer to [Number Formatter](#2-number-formatter) for details). > [!Tip] > You can store the populated `of` function in a custom formatter: @@ -71,7 +71,7 @@ const numberValue = format.number.of(123.45); // "123.45" - `.unit(string)`: Adds a unit to the number (e.g., "$", "%"). - `.locale(string)`: Formats the number according to the specified locale. - `.readable()`: Makes the value more readable for small numbers. -- `.default(string)`: Sets a default value in case value is `null` or `undefined`. +- `.default(string)`: Sets a default value in case `value` (or `decimals`) is `null` or `undefined`. ### 3. Commas Formatter diff --git a/packages/morpho-ts/src/format/format/format.test.ts b/packages/morpho-ts/src/format/format/format.test.ts index 72982719..744e3562 100644 --- a/packages/morpho-ts/src/format/format/format.test.ts +++ b/packages/morpho-ts/src/format/format/format.test.ts @@ -14,6 +14,10 @@ describe("format", () => { expect(format.hex.default("default").of(undefined)).toEqual("default"); expect(format.hex.default("default").of(null)).toEqual("default"); }); + it("with nullable values", () => { + expect(format.hex.of(undefined)).toEqual(undefined); + expect(format.hex.of(null)).toEqual(null); + }); }); describe("should properly format bigint in hex format", () => { it("without option", () => { @@ -26,6 +30,20 @@ describe("format", () => { "default", ); expect(format.hex.default("default").of(null, 18)).toEqual("default"); + expect(format.hex.default("default").of(bigint, undefined)).toEqual( + "default", + ); + expect(format.hex.default("default").of(bigint, null)).toEqual( + "default", + ); + }); + it("with nullable values", () => { + expect(format.hex.of(undefined, decimals)).toEqual(undefined); + expect(format.hex.of(null, decimals)).toEqual(null); + expect(format.hex.of(bigint, undefined)).toEqual(undefined); + expect(format.hex.of(bigint, null)).toEqual(null); + expect(format.hex.of(null, undefined)).toEqual(null); + expect(format.hex.of(undefined, null)).toEqual(undefined); }); }); }); @@ -76,6 +94,10 @@ describe("format", () => { ); expect(format.number.default("default").of(null)).toEqual("default"); }); + it("with nullable values", () => { + expect(format.number.of(undefined)).toEqual(undefined); + expect(format.number.of(null)).toEqual(null); + }); }); describe("should properly format bigint in number format", () => { it("without option", () => { @@ -126,6 +148,20 @@ describe("format", () => { expect(format.number.default("default").of(null, 18)).toEqual( "default", ); + expect(format.number.default("default").of(bigint, undefined)).toEqual( + "default", + ); + expect(format.number.default("default").of(bigint, null)).toEqual( + "default", + ); + }); + it("with nullable values", () => { + expect(format.number.of(undefined, decimals)).toEqual(undefined); + expect(format.number.of(null, decimals)).toEqual(null); + expect(format.number.of(bigint, undefined)).toEqual(undefined); + expect(format.number.of(bigint, null)).toEqual(null); + expect(format.number.of(null, undefined)).toEqual(null); + expect(format.number.of(undefined, null)).toEqual(undefined); }); }); }); @@ -170,6 +206,10 @@ describe("format", () => { ); expect(format.short.default("default").of(null)).toEqual("default"); }); + it("with nullable values", () => { + expect(format.short.of(undefined)).toEqual(undefined); + expect(format.short.of(null)).toEqual(null); + }); }); describe("should properly format bigint in short format", () => { it("without option", () => { @@ -230,6 +270,20 @@ describe("format", () => { "default", ); expect(format.short.default("default").of(null, 18)).toEqual("default"); + expect(format.short.default("default").of(bigint, undefined)).toEqual( + "default", + ); + expect(format.short.default("default").of(bigint, null)).toEqual( + "default", + ); + }); + it("with nullable values", () => { + expect(format.short.of(undefined, decimals)).toEqual(undefined); + expect(format.short.of(null, decimals)).toEqual(null); + expect(format.short.of(bigint, undefined)).toEqual(undefined); + expect(format.short.of(bigint, null)).toEqual(null); + expect(format.short.of(null, undefined)).toEqual(null); + expect(format.short.of(undefined, null)).toEqual(undefined); }); }); }); @@ -271,6 +325,10 @@ describe("format", () => { ); expect(format.commas.default("default").of(null)).toEqual("default"); }); + it("with nullable values", () => { + expect(format.commas.of(undefined)).toEqual(undefined); + expect(format.commas.of(null)).toEqual(null); + }); }); describe("should properly format bigint in commas format", () => { it("without option", () => { @@ -322,6 +380,20 @@ describe("format", () => { expect(format.commas.default("default").of(null, 18)).toEqual( "default", ); + expect(format.commas.default("default").of(bigint, undefined)).toEqual( + "default", + ); + expect(format.commas.default("default").of(bigint, null)).toEqual( + "default", + ); + }); + it("with nullable values", () => { + expect(format.commas.of(undefined, decimals)).toEqual(undefined); + expect(format.commas.of(null, decimals)).toEqual(null); + expect(format.commas.of(bigint, undefined)).toEqual(undefined); + expect(format.commas.of(bigint, null)).toEqual(null); + expect(format.commas.of(null, undefined)).toEqual(null); + expect(format.commas.of(undefined, null)).toEqual(undefined); }); }); }); @@ -362,6 +434,10 @@ describe("format", () => { ); expect(format.percent.default("default").of(null)).toEqual("default"); }); + it("with nullable values", () => { + expect(format.percent.of(undefined)).toEqual(undefined); + expect(format.percent.of(null)).toEqual(null); + }); }); describe("should properly format bigint in percent format", () => { it("without option", () => { @@ -409,6 +485,20 @@ describe("format", () => { expect(format.percent.default("default").of(null, 18)).toEqual( "default", ); + expect(format.percent.default("default").of(bigint, undefined)).toEqual( + "default", + ); + expect(format.percent.default("default").of(bigint, null)).toEqual( + "default", + ); + }); + it("with nullable values", () => { + expect(format.percent.of(undefined, decimals)).toEqual(undefined); + expect(format.percent.of(null, decimals)).toEqual(null); + expect(format.percent.of(bigint, undefined)).toEqual(undefined); + expect(format.percent.of(bigint, null)).toEqual(null); + expect(format.percent.of(null, undefined)).toEqual(null); + expect(format.percent.of(undefined, null)).toEqual(undefined); }); }); }); diff --git a/packages/morpho-ts/src/format/format/format.ts b/packages/morpho-ts/src/format/format/format.ts index e09e15be..4d101099 100644 --- a/packages/morpho-ts/src/format/format/format.ts +++ b/packages/morpho-ts/src/format/format/format.ts @@ -265,7 +265,10 @@ function formatBI( } type FormatterWithDefault = { - of(value: bigint | null | undefined, decimals: number): string; + of( + value: bigint | null | undefined, + decimals: number | null | undefined, + ): string; of(value: number | null | undefined): string; } & { [K in keyof Omit]: F[K] extends (...args: infer A) => F @@ -284,15 +287,19 @@ export abstract class BaseFormatter { return this as FormatterWithDefault; } - of( + of( value: T, - decimals: number, - ): Exclude | string; + decimals: D, + ): Exclude | Exclude | string; of( value: T, ): Exclude | string; - of(value: bigint | number, decimals?: number) { - if (value == null) return this._options.default ?? value; + of( + value: bigint | number | null | undefined, + decimals?: number | null | undefined, + ) { + if (value == null || (typeof value === "bigint" && decimals == null)) + return this._options.default ?? (value == null ? value : decimals); if (typeof value === "number") { const str = value.toString();