Skip to content

Instantly share code, notes, and snippets.

@jessealama
Created January 22, 2025 14:12
Show Gist options
  • Save jessealama/8b0ecbdbda1488e17d369733567765a4 to your computer and use it in GitHub Desktop.
Save jessealama/8b0ecbdbda1488e17d369733567765a4 to your computer and use it in GitHub Desktop.
Type definitions for a two-class approach to Measure & Decimal
// Sketching a two-class world for Measure + Decimal with
//
// 1. A Decimal class (normalized subset of IEEE 754 Decimal128), with arithmetic, comparisons, formatting
// 2. A 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(x: string | number | bigint);
// predicates
isFinite(): boolean;
isNegative(): boolean;
isNaN(): boolean;
isZero(): boolean;
// comparison
equals(other: Decimal): boolean;
lessThan(other: Decimal): boolean;
// more comparisons, probably needed because of NaN pollution
// (NaN is not equal to itself, NaN is not less than itself, etc.)
notEquals(other: Decimal): boolean;
lessThanOrEquals(other: Decimal): boolean;
greaterThen(other: Decimal): boolean;
greaterThanOrEquals(other: Decimal): boolean;
// arithmetic
abs(): Decimal;
add(x: Decimal): Decimal;
divide(x: Decimal): Decimal;
multiply(x: Decimal): Decimal;
negate(): Decimal;
subtract(x: Decimal): Decimal;
// 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
toFixed(opts?: {digits?: number, roundingMode?: RoundingMode}): string;
toJSON(): string;
toLocaleString(locale?: string): string;
toPrecision(opts?: {digits?: number, roundingMode?: RoundingMode}): string;
toString(): string;
// rounding
round(numFractionalDigits: number, mode: RoundingMode): Decimal;
// conversion
toNumber(): number;
toBigInt(): bigint; // throws if not mathematically an integer
toMeasure(unit?: string, precision?: number): Measure;
}
type ExpandedNumber = string // digit strings, not arbitrary strings
| number
| bigint
| Decimal;
type PrecisionType = "fractionalDigits" | "significantDigits";
export declare class Measure {
constructor(value: ExpandedNumber, opts?: { unit?: string, precision?: number, precisionType?: PrecisionType });
convertTo(unit: string, precision?: number): Measure;
toString(): string;
toComponents(): {value: ExpandedNumber, unit: string}[];
value(): ExpandedNumber; // same type as the value passed to the constructor
unit(): string | undefined;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment