Skip to content

isentropic-dev/dim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

64 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dim

Type-safe dimensional analysis and units for TypeScript.

Just want SI? @isentropic/dim-si provides ready-to-use SI units with compile-time dimension checking.

How It Works

dim treats quantities and units as separate concepts with different responsibilities. Units are layered on top of quantities to give them meaning.

A quantity encodes dimensionality. Dimensions are tracked at compile time, so the type checker catches errors like adding a length to a time before your code runs.

A unit gives meaning to a quantity. Units are views over quantities: different lenses for reading and writing the same underlying value.

dim accomplishes this by providing tools for defining quantity and unit systems, and uses those same tools to provide ready-made ISQ quantities and SI units.

End-to-End Example

Here's what that looks like in practice: a small physics system with length, time, and temperature.

1. Define a quantity system

Choose base dimensions and derive compound quantities from them:

import { defineQuantitySystem } from "@isentropic/dim-quantity";

const qs = defineQuantitySystem(["L", "T", "Θ"]);

const length = qs.base("L");
const time = qs.base("T");
const temperature = qs.base("Θ");
const velocity = qs.factory({ L: 1, T: -1, Θ: 0 });

At this point, length(100) produces a value tagged with dimension L. No units, no scale factors, just dimensionality.

For larger systems, dim-quantity supports a spec-based approach with code generation.

2. Layer a unit system on top

Units attach physical meaning to those raw quantities:

import { defineUnitSystem, valueIn } from "@isentropic/dim-unit";

const us = defineUnitSystem("tutorial", qs);

// Base units
const meter = us.unit(length);
const second = us.unit(time);
const kelvin = us.unit(temperature);

// Scaled units
const kilometer = meter.scaled(1000);
const hour = second.scaled(3600);

// Affine units (arbitrary zero point)
const celsius = kelvin.offset(273.15);

3. Use the units to solve problems

Now you have type-safe arithmetic with automatic dimension tracking. Wrap any quantity with q() for fluent chaining:

import { q } from "@isentropic/dim-unit/chain";

const speed = q(kilometer(5)).div(hour(2));

q(kilometer(5)).in(meter); // 5000
q(kilometer(5)).in(kilometer); // 5

// Same-dimension arithmetic works
q(kilometer(1)).plus(meter(500)); // 1500 m

// Dimension mismatches are compile errors
q(kilometer(1)).plus(hour(1)); // Error: length and time dimensions don't match

// Affine units enforce correct semantics
q(celsius(100)).minus(celsius(0)); // 100 K (linear delta)
q(celsius(0)).plus(celsius.delta(10)); // 10°C (affine point)
q(celsius(100)).plus(celsius(0)); // Error: can't add two affine quantities

Free functions are also available for one-off operations:

import { add, divide } from "@isentropic/dim-unit/ops";

const total = add(kilometer(1), meter(500));
const speed = divide(kilometer(5), hour(2));

Pre-Built Systems

Defining quantity and unit systems from scratch is useful for custom domains, but most scientific and engineering work uses the same foundational systems: the ISQ (International System of Quantities) for dimensions and derived quantities, and the SI (International System of Units) for units.

Rather than make everyone define these themselves, dim uses its own tooling to provide them as ready-to-use packages.

Packages

Package Description
dim-si SI unit system built on dim-isq
dim-isq ISQ quantity system
dim-unit Define unit systems with scale factors and affine offsets for any quantity system
dim-quantity Define quantity systems with compile-time dimension tracking

Development

deno test    # Run all tests
deno lint    # Lint all files
deno fmt     # Format all files

License

MIT

About

Compile-time dimensional analysis and units for TypeScript

Topics

Resources

License

Contributing

Stars

Watchers

Forks