Skip to content

Instantly share code, notes, and snippets.

@jessealama
Created January 22, 2025 14:24
Show Gist options
  • Save jessealama/c4d9036789a9758239bfa375217bd35b to your computer and use it in GitHub Desktop.
Save jessealama/c4d9036789a9758239bfa375217bd35b to your computer and use it in GitHub Desktop.
Type definitions for a three-class approach to Measure & Decimal
// Sketching a three-class world for Measure + Decimal with
//
// 1. IEEE 754 Decimal128 class, with no arithmetic, (mathematical) equality checking only, formatting
// 2. Decimal class (normalized subset of IEEE 754 Decimal128), with arithmetic, comparisons, formatting
// 3. Measure class (minimal in 262, fleshed out in 402), no arithmetic
type RoundingMode =
| "ceil"
| "floor"
| "trunc"
| "halfEven"
| "halfExpand"; // the default, same as Number and Math
export declare class Decimal {
constructor(value: string | number | bigint | NormalizedDecimal);
// predicates
isFinite(): boolean;
isNegative(): boolean;
isNaN(): boolean;
isZero(): boolean;
// comparison
equals(other: Decimal): boolean; // mathematical equality
lessThan(other: Decimal): boolean; // do we need this?
// serialization
toJSON(): string;
toString(): string;
toFixed(opts?: {digits?: number}): string;
toLocaleString(locale?: string): string;
toPrecision(opts?: {digits?: number}): string;
// no arithmetic
// no rounding
// conversion
toNumber(): number;
toBigInt(): bigint;
toNormalizedDecimal(): NormalizedDecimal; // or just "normalize"?
}
export declare class NormalizedDecimal { // or just "Decimal"?
constructor(x: string | number | bigint | Decimal);
// predicates
isFinite(): boolean;
isNegative(): boolean;
isNaN(): boolean;
isZero(): boolean;
// comparison
equals(other: NormalizedDecimal): boolean;
lessThan(other: NormalizedDecimal): boolean;
// arithmetic
abs(): NormalizedDecimal;
add(x: NormalizedDecimal): NormalizedDecimal;
divide(x: NormalizedDecimal): NormalizedDecimal;
multiply(x: NormalizedDecimal): NormalizedDecimal;
negate(): NormalizedDecimal;
subtract(x: NormalizedDecimal): NormalizedDecimal;
// Somewhat more advanced mathematical operations, elementary, can be included without much implementation hassle
sqrt(): Decimal;
// Even more advanced (non-elementary) Conceptually within scope but not as common.
// Leaning toward not including any of these because of implementation complexity and relative lack of use cases.
// Even more trigonometric functions could conceivably be included, but these are probably the
// most common ones. IEEE 754 includes a list of recommended mathematical operations that includes these
// and more.
exp(): Decimal;
pow(x: Decimal): Decimal;
ln(): Decimal;
log10(): Decimal;
sin(): Decimal;
cos(): Decimal;
tan(): Decimal;
asin(): Decimal;
acos(): Decimal;
atan(): Decimal;
// serlialization
toJSON(): string;
toString(): string;
toFixed(opts?: {digits?: number, roundingMode?: RoundingMode}): string;
toLocaleString(locale?: string): string;
toPrecision(opts?: {digits?: number, roundingMode?: RoundingMode}): string;
// rounding
round(numFractionalDigits: number, mode: RoundingMode): NormalizedDecimal;
// conversion
toDecimal128(): Decimal;
toNumber(): number;
toBigInt(): bigint;
}
type ExpandedNumber = string // digit strings, not arbitrary strings
| number
| bigint
| Decimal
| NormalizedDecimal;
export declare class Measure {
constructor(value: ExpandedNumber, unit?: string, precision?: number);
convertTo(unit: string, precision?: number): Measure;
toString(): string;
toComponents(): {value: ExpandedNumber, unit: string}[];
value(): ExpandedNumber;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment