UNPKG

@fractorysolutions/safe-units

Version:
100 lines (81 loc) 3.08 kB
import { AddendOf, AddExponents, DivideExponents, Exponent, MultiplicandOf, MultiplyExponents, PositiveExponent, ProductOf, SubtractExponents, SubtrahendOf, } from "../exponent"; export type Unit = { [dimension: string]: Exponent | undefined; }; export type UnitWithSymbols<U extends Unit = Unit> = { [D in keyof U]+?: [string, NonNullable<U[D]>]; }; export type SymbolAndExponent = [string, Exponent]; // Multiplication /** Returns the product of two units. This is the sum of two dimension vectors. */ export type MultiplyUnits<L extends Unit, R extends Unit> = { [Dim in keyof L | keyof R]: AddExponents< GetExponent<L, Dim>, GetExponent<R, Dim> >; }; /** A type that is assignable from all units that can be multiplied by U without producing an error. */ export type MultiplicandUnit<U extends Unit> = Partial<{ [D in keyof U]: AddendOf<CleanExponent<U[D]>>; }> & Unit; // Division /** Returns the quotient of two units. This is the difference of two dimension vectors. */ export type DivideUnits<L extends Unit, R extends DivisorUnit<L>> = { [Dim in keyof L | keyof R]: SubtractExponents< GetExponent<L, Dim>, GetExponent<R, Dim> >; }; /** A type that is assignable from all units that U can be divided by without producing an error. */ export type DivisorUnit<U extends Unit> = | U // unit can always be divided by itself, but typescript doesn't quite figure that out | (Partial<{ [D in keyof U]: SubtrahendOf<CleanExponent<U[D]>> }> & Unit); // Exponentiation /** Returns the unit raised to a power. This is the scalar multiple of the dimension vector. */ export type ExponentiateUnit<U extends Unit, N extends Exponent> = "0" extends N ? Record<never, Exponent | undefined> : { [Dim in keyof U]: MultiplyExponents<GetExponent<U, Dim>, N> }; /** Returns the union of exponents to which a given unit is allowed to be raised. */ export type AllowedExponents<U extends Unit> = | Exclude<Exponent, NonAllowedExponents<U>> | "-1" | "0" | "1"; /** Returns the union of exponents that raising and exponent to would produce an error. */ type NonAllowedExponents<U extends Unit> = { [Dim in keyof U]: undefined extends U[Dim] ? never : Exclude<Exponent, MultiplicandOf<NonNullable<U[Dim]>>>; }[keyof U]; // Roots /** Returns the nth root of a unit. This is the inverse scalar multiple of the dimension vector. */ export type NthRootUnit< U extends RadicandUnit<N>, N extends PositiveExponent, > = 1 extends N ? U : { [Dim in keyof U]: DivideExponents<GetExponent<U, Dim>, N> }; /** A type that is assignable from all units whose Nth root does not produce an error. */ export type RadicandUnit<N extends PositiveExponent> = { [dimension: string]: ProductOf<N> | undefined; }; // Utility types /** Get the exponent at a given dimension of a unit, or 0 if that dimension is undefined */ type GetExponent<U extends Unit, D> = D extends keyof U ? NonNullable<U[D]> : "0"; type CleanExponent<E extends undefined | Exponent> = undefined extends E ? "0" : NonNullable<E>;