Skip to main content

Overview

Univerto is built with TypeScript and provides full type safety for all conversions. Each converter module exports its own unit types, and the core library provides shared type definitions.

Unit Types

Each converter module defines its own unit type and constant object.

Pattern

All unit types follow this pattern:
// Type extracted from constant object
export type LengthUnit = (typeof LENGTH_UNIT)[keyof typeof LENGTH_UNIT];

// Frozen constant object with unit values
export const LENGTH_UNIT = Object.freeze({
  METER: 'meter',
  KILOMETER: 'kilometer',
  // ...
});

Example: Length Units

import { LENGTH_UNIT, LengthUnit } from 'univerto/length';

// Type: LengthUnit = 'meter' | 'kilometer' | 'centimeter' | ...
const unit: LengthUnit = LENGTH_UNIT.METER;

// Available length units
const LENGTH_UNIT = {
  NANOMETER: 'nanometer',
  MICROMETER: 'micrometer',
  MILLIMETER: 'millimeter',
  CENTIMETER: 'centimeter',
  METER: 'meter',
  KILOMETER: 'kilometer',
  INCH: 'inch',
  HAND: 'hand',
  FOOT: 'foot',
  YARD: 'yard',
  CHAIN: 'chain',
  FURLONG: 'furlong',
  MILE: 'mile',
  LEAGUE: 'league'
};

Other Unit Types

Each converter follows the same pattern:
import { MASS_UNIT, MassUnit } from 'univerto/mass';
import { TIME_UNIT, TimeUnit } from 'univerto/time';
import { VOLUME_UNIT, VolumeUnit } from 'univerto/volume';
import { AREA_UNIT, AreaUnit } from 'univerto/area';
import { SPEED_UNIT, SpeedUnit } from 'univerto/speed';
import { DATA_UNIT, DataUnit } from 'univerto/data';
import { CURRENT_UNIT, CurrentUnit } from 'univerto/current';
import { VOLTAGE_UNIT, VoltageUnit } from 'univerto/voltage';
import { FREQUENCY_UNIT, FrequencyUnit } from 'univerto/frequency';

Fraction Interface

Returned by the convertToFraction() method.
interface Fraction {
  numerator: number;
  denominator: number;
}

Properties

numerator
number
The numerator of the fraction
denominator
number
The denominator of the fraction

Usage

import { LengthUnitConverter } from 'univerto/length';
import { LENGTH_UNIT } from 'univerto/length';

const fraction = LengthUnitConverter
  .from(1, LENGTH_UNIT.INCH)
  .to(LENGTH_UNIT.CENTIMETER)
  .convertToFraction();

// fraction: { numerator: number, denominator: number }
const decimal = fraction.numerator / fraction.denominator;

Rational Class

The Rational class is used internally for high-precision conversions.
class Rational {
  constructor(numerator: number, denominator: number);
  
  static fromNumber(number: number): Rational;
  static pow(base: number, exp: number): Rational;
  
  toNumber(): number;
  toFraction(): { numerator: number; denominator: number };
  
  multiply(other: Rational): Rational;
  divide(other: Rational): Rational;
}

Constructor

const rational = new Rational(3, 4); // Represents 3/4
numerator
number
required
The numerator of the rational number
denominator
number
required
The denominator of the rational number

Static Methods

fromNumber()

Creates a Rational from a decimal number.
const rational = Rational.fromNumber(5);
// Equivalent to new Rational(5, 1)
number
number
required
The number to convert to a Rational

pow()

Calculates a power as a Rational.
const squared = Rational.pow(10, 2);
// Returns Rational(100, 1)

const inverse = Rational.pow(10, -2);
// Returns Rational(1, 100)
base
number
required
The base number
exp
number
required
The exponent (can be negative)

Instance Methods

toNumber()

Converts the Rational to a decimal number.
const rational = new Rational(3, 4);
const decimal = rational.toNumber(); // 0.75

toFraction()

Converts the Rational to a Fraction object.
const rational = new Rational(3, 4);
const fraction = rational.toFraction();
// { numerator: 3, denominator: 4 }

multiply()

Multiplies two Rational numbers.
const a = new Rational(2, 3);
const b = new Rational(3, 4);
const result = a.multiply(b);
// Rational(6, 12) = 0.5
other
Rational
required
The Rational to multiply by

divide()

Divides two Rational numbers.
const a = new Rational(2, 3);
const b = new Rational(3, 4);
const result = a.divide(b);
// Rational(8, 9) ≈ 0.888...
other
Rational
required
The Rational to divide by

Unit Scale Type

Defines the internal scale representation for each unit.
type UnitScale = {
  base: number;
  exponent: number;
}

Properties

base
number
The base value for the unit scale (e.g., 10 for metric units)
exponent
number
The exponent applied to the base (e.g., -3 for millimeters)

Usage

This type is used internally to define conversion scales:
// Example: Meter scale definition
const meterScale: UnitScale = {
  base: 10,
  exponent: 0
};

// Example: Kilometer scale definition
const kilometerScale: UnitScale = {
  base: 10,
  exponent: 3
};
Note: This type is primarily for internal use and custom converter creation.

Generic Type Parameters

The converter factory uses TypeScript generics to ensure type safety.
function createPreciseConverter<
  S extends Record<string, Rational>,
  Unit extends keyof S
>(scale: S)

Type Parameters

S
Record<string, Rational>
A record mapping unit names to their Rational scale values
Unit
keyof S
The union type of all valid unit keys from the scale

How It Works

The createPreciseConverter function and Rational class are internal utilities used by Univerto to create all the unit converters. They ensure type safety across the conversion methods. The generic types guarantee that:
  • fromUnit and targetUnit must be valid keys from the scale object
  • Type inference propagates through the method chain
  • Invalid units are caught at compile time
This is why you get full TypeScript autocomplete and type checking when using any converter:
import { TimeUnitConverter, TIME_UNIT } from 'univerto/time';

// TypeScript knows exactly which units are valid
TimeUnitConverter.from(10, TIME_UNIT.HOUR);  // ✓ Valid
TimeUnitConverter.from(10, 'invalid');       // ✗ Type error

Type Exports

Each converter module exports its types:
// Length module
export { LENGTH_UNIT, LengthUnit } from 'univerto/length';

// Mass module
export { MASS_UNIT, MassUnit } from 'univerto/mass';

// Time module
export { TIME_UNIT, TimeUnit } from 'univerto/time';

// And so on...

Importing Types

import type { LengthUnit } from 'univerto/length';
import type { MassUnit } from 'univerto/mass';

// Use in function signatures
function convertLength(value: number, from: LengthUnit, to: LengthUnit) {
  return LengthUnitConverter.from(value, from).to(to).convert();
}

Example Type Usage

Type-Safe Converter Function

import { LengthUnitConverter, LENGTH_UNIT, LengthUnit } from 'univerto/length';

function convert(
  value: number,
  fromUnit: LengthUnit,
  toUnit: LengthUnit
): number {
  return LengthUnitConverter
    .from(value, fromUnit)
    .to(toUnit)
    .convert();
}

// TypeScript ensures type safety
const meters = convert(100, LENGTH_UNIT.CENTIMETER, LENGTH_UNIT.METER); // ✓
const invalid = convert(100, 'invalid', LENGTH_UNIT.METER); // ✗ Type error

Generic Conversion Function

type Converter<Unit> = {
  from(value: number, unit: Unit): {
    to(unit: Unit): {
      convert(): number;
      convertToFraction(): { numerator: number; denominator: number };
    };
  };
};

function genericConvert<Unit>(
  converter: Converter<Unit>,
  value: number,
  from: Unit,
  to: Unit
): number {
  return converter.from(value, from).to(to).convert();
}

// Works with any converter
genericConvert(LengthUnitConverter, 100, LENGTH_UNIT.CM, LENGTH_UNIT.M);
genericConvert(MassUnitConverter, 1000, MASS_UNIT.GRAM, MASS_UNIT.KG);

See Also

Build docs developers (and LLMs) love