@fractorysolutions/safe-units
Version:
Type-safe TypeScript units of measure
57 lines (56 loc) • 3 kB
TypeScript
import { Exponent } from "../exponent";
import { GenericMeasure, NumericOperations } from "./genericMeasure";
import { GenericMeasureStatic } from "./genericMeasureStatic";
import { IsSingleStringLiteral } from "./typeUtils";
import { Unit } from "./unitTypeArithmetic";
type DimensionResult<N, D extends string> = true extends IsSingleStringLiteral<D> ? GenericMeasure<N, {
[Dim in D]: "1";
}> : never;
/** The functions needed to construct a measure of a given numeric type */
interface GenericMeasureFactory<N> {
/** The constructor for this generic measure type, useful for doing `instanceof` checks. */
isMeasure(value: any): value is GenericMeasure<N, any>;
/**
* Creates a new dimension base unit.
* @param dim a unique string literal which names this dimension (e.g. "length")
* @param symbol the symbol of the base unit of the dimension (e.g. "m")
* @returns A measure representing 1 base unit of the dimension (1 m)
*/
dimension<D extends string>(dim: D, symbol?: string): DimensionResult<N, D>;
/**
* Creates a dimensionless measure.
* @param value the value of the measure
* @returns a measure with no dimensions
*/
dimensionless(value: N): GenericMeasure<N, Record<never, Exponent | undefined>>;
/**
* Creates a measure as a multiple of another measure.
* @param value the number of measures
* @param quantity the measure to be multiplied
* @param symbol an optional unit symbol for this measure
* @returns a measure of value number of quantities.
*/
of<U extends Unit>(value: N, quantity: GenericMeasure<N, U>, symbol?: string): GenericMeasure<N, U>;
}
type GenericMeasureCommon<N> = GenericMeasureFactory<N> & GenericMeasureStatic<N>;
type Omit<T, K extends string> = Pick<T, Exclude<keyof T, K>>;
/**
* A complete measure type for a given numeric type. This consists of:
* - Static methods to construct measures (e.g. `Measure.of`)
* - Predefined arithmetic static methods (e.g. `Measure.add`)
* - User defined static methods (e.g. `Measure.abs`)
*/
export type GenericMeasureType<N, StaticMethods extends object> = GenericMeasureCommon<N> & Omit<StaticMethods, keyof GenericMeasureCommon<N>>;
/**
* Creates a new measure factory for a given numeric type. The numeric type of the measure is inferred from the
* parameter.
* @param num the set of numeric operations needed to implement a measure for an arbitrary numeric type
* @param staticMethods an object containing methods that should be spread into the static definition of a measure,
* useful for attaching static math operations to the type.
* @returns a factory for constructing measures of the given numeric type
* @example
* type MyMeasure<U extends Unit> = GenericMeasure<MyNumberType, U>;
* const MyMeasure = createMeasureType({ ... });
*/
export declare function createMeasureType<N, S extends object = object>(num: NumericOperations<N>, staticMethods?: S): GenericMeasureType<N, S>;
export {};