@fractorysolutions/safe-units
Version:
Type-safe TypeScript units of measure
68 lines (56 loc) • 1.78 kB
text/typescript
import {
getExponentValue,
negateExponent,
} from "../exponent/exponentValueArithmetic";
import { SymbolAndExponent, UnitWithSymbols } from "./unitTypeArithmetic";
export function defaultFormatUnit(unit: UnitWithSymbols): string {
const dimensions = Object.keys(unit)
.map((dimension) => unit[dimension])
.filter(isDimensionPresent)
.sort(orderDimensions);
if (dimensions.length === 0) {
return "";
}
const positive = dimensions.filter(([_, dim]) => getExponentValue(dim) > 0);
const negative = dimensions.filter(([_, dim]) => getExponentValue(dim) < 0);
if (positive.length === 0) {
return formatDimensions(negative);
}
const numerator = formatDimensions(positive);
if (negative.length === 0) {
return numerator;
}
const denominator = formatDimensions(negative.map(negateDimension));
return `${numerator} / ${maybeParenthesize(
denominator,
negative.length !== 1,
)}`;
}
function isDimensionPresent(
dimension: SymbolAndExponent | undefined,
): dimension is SymbolAndExponent {
return dimension !== undefined && dimension[1] !== "0";
}
function orderDimensions(
[leftSymbol]: SymbolAndExponent,
[rightSymbol]: SymbolAndExponent,
): number {
return leftSymbol < rightSymbol ? -1 : 1;
}
function formatDimensions(dimensions: SymbolAndExponent[]): string {
return dimensions
.map(([symbol, exponent]) => {
const exponentStr = exponent !== "1" ? `^${exponent}` : "";
return `${symbol}${exponentStr}`;
})
.join(" * ");
}
function negateDimension([
symbol,
exponent,
]: SymbolAndExponent): SymbolAndExponent {
return [symbol, negateExponent(exponent)];
}
function maybeParenthesize(text: string, parenthesize: boolean): string {
return parenthesize ? `(${text})` : text;
}