@typesugar/type-system
v0.1.0
Published
π§ Type-level programming utilities and macros for typesugar
Maintainers
Readme
@typesugar/type-system
Advanced type system extensions for TypeScript.
Overview
@typesugar/type-system extends TypeScript with powerful type-level features from the "too hard basket" β things the TypeScript team deemed too complex to add to the language. All implemented through compile-time macros.
Installation
npm install @typesugar/type-system
# or
pnpm add @typesugar/type-systemFeatures
Type-Level Boolean Utilities
Pure type-level boolean logic for compile-time type assertions and comparisons.
import {
type Equal,
type Extends,
type Not,
type And,
type Or,
type IsNever,
type IsAny,
type IsUnknown,
} from "@typesugar/type-system";
// Type-level equality check
type Test1 = Equal<string, string>; // true
type Test2 = Equal<string, number>; // false
// Subtype check
type Test3 = Extends<"hello", string>; // true
// Boolean combinators
type Test4 = And<true, true>; // true
type Test5 = Or<false, true>; // true
type Test6 = Not<false>; // true
// Special type checks
type Test7 = IsNever<never>; // true
type Test8 = IsAny<any>; // true
type Test9 = IsUnknown<unknown>; // trueNewtype (Zero-Cost Branding)
Branded types that compile away completely β type-safe wrappers with zero runtime cost.
import {
type Newtype,
wrap,
unwrap,
newtypeCtor,
validatedNewtype,
} from "@typesugar/type-system";
// Define branded types
type UserId = Newtype<number, "UserId">;
type Meters = Newtype<number, "Meters">;
// Wrap values (compiles away to nothing)
const id = wrap<UserId>(42);
const raw = unwrap(id);
// Type-safe! Can't mix up UserId and Meters
function getUser(id: UserId): User { ... }
getUser(wrap<UserId>(42)); // OK
getUser(42); // Type error!
// Constructor factory
const mkUserId = newtypeCtor<UserId>();
const id2 = mkUserId(42);
// Validated constructor (validation runs, wrapping is zero-cost)
const mkEmail = validatedNewtype<Email>(s => s.includes("@"));The Branding Spectrum
This module provides three levels of type branding:
| Level | Type | Runtime Cost | Use Case |
| ----------- | ---------------------- | ------------ | --------------------------------------- |
| Newtype | Newtype<Base, Brand> | Zero | Type discrimination (UserId, Meters) |
| Opaque | Opaque<Base, Brand> | Minimal | Hidden representation (Password, Token) |
| Refined | Refined<Base, R> | Validation | Runtime constraints (Email, Port) |
Higher-Kinded Types (HKT)
Type constructors as type parameters via indexed-access encoding.
import {
type $,
type Kind,
type ArrayF,
type PromiseF,
} from "@typesugar/type-system";
// F is a type constructor (Array, Promise, etc.)
interface Functor<F extends Kind> {
map<A, B>(fa: $<F, A>, f: (a: A) => B): $<F, B>;
}
// Apply a type constructor
type Result = $<ArrayF, number>; // number[]
type AsyncResult = $<PromiseF, string>; // Promise<string>Existential Types
"There exists some type T" with CPS encoding β heterogeneous collections, type-safe plugins.
import {
type Exists,
packExists,
useExists,
type Showable,
showable,
} from "@typesugar/type-system";
// Pack a value with its witness
const items: Showable[] = [
showable(42, numShow),
showable("hello", strShow),
showable(true, boolShow),
];
// Safely use each item
for (const item of items) {
console.log(showValue(item)); // Type-safe despite heterogeneous types
}Refinement Types
Types with predicates β Byte, Port, NonEmpty, Email β with compile-time validation for literals.
import {
type Refined,
Positive,
NonEmpty,
Email,
Port,
} from "@typesugar/type-system";
// Refined types carry their constraints
type PositiveInt = Refined<number, typeof Positive>;
type ValidEmail = Refined<string, typeof Email>;
type ValidPort = Refined<number, typeof Port>;
// Compile-time validation for literals
const port = refine<Port>(8080); // β
const badPort = refine<Port>(-1); // β Compile errorType-Level Arithmetic
Compile-time numeric computation.
import { Add, Sub, Mul, Div, Mod, Pow } from "@typesugar/type-system";
type Sum = Add<1, 2>; // 3
type Diff = Sub<10, 3>; // 7
type Product = Mul<4, 5>; // 20
type Quotient = Div<20, 4>; // 5
type Remainder = Mod<17, 5>; // 2
type Power = Pow<2, 8>; // 256Length-Indexed Arrays (Vec)
Arrays with compile-time known length β type-safe head/tail, concatenation, zip.
import { Vec, type Add, type Sub } from "@typesugar/type-system";
// Create length-indexed vectors
const v3: Vec<number, 3> = Vec.from([1, 2, 3]);
const v0: Vec<string, 0> = Vec.empty();
const v5: Vec<number, 5> = Vec.fill(0, 5);
// Length is part of the type
const len: 3 = Vec.length(v3); // Type is literal 3, not number
// Safe head/tail (compile error on empty)
const first: number = Vec.head(v3); // β
const rest: Vec<number, 2> = Vec.tail(v3); // β
// Vec.head(v0); // β Compile error: Vec<string, 0> has no head
// Type-preserving operations
const v4: Vec<number, 4> = Vec.cons(0, v3); // Add<3, 1> = 4
const v6: Vec<number, 6> = Vec.concat(v3, v3); // Add<3, 3> = 6
const pairs: Vec<[number, string], 3> = Vec.zip(v3, Vec.from(["a", "b", "c"]));
// Use with contracts: length is provable
function processTriple(v: Vec<number, 3>): number {
requires(Vec.length(v) === 3); // PROVEN: type fact
return Vec.head(v) + Vec.last(v);
}Key properties for contract proofs:
Vec<T, N>.length === N(type fact)Vec.head(v)is safe whenN > 0(non-empty)Vec.concat(a, b)producesVec<T, Add<N, M>>
Opaque Type Modules
ML-style abstract types with controlled access.
import { opaqueModule, type OpaqueModule } from "@typesugar/type-system";
// Define an opaque type with smart constructor
const UserId = opaqueModule<number, "UserId">({
validate: (n) => n > 0,
error: "UserId must be positive",
});
const id = UserId.make(42); // β UserId
const bad = UserId.make(-1); // Throws: "UserId must be positive"
const raw = UserId.unwrap(id); // numberPhantom Type State Machines
Encode state machines in the type system.
import { createStateMachine, type Phantom } from "@typesugar/type-system";
type DoorState = "open" | "closed" | "locked";
const Door = createStateMachine<DoorState>()
.state("closed", { open: "open", lock: "locked" })
.state("open", { close: "closed" })
.state("locked", { unlock: "closed" })
.build();
// Type-safe transitions
const closed = Door.initial("closed");
const open = Door.transition(closed, "open"); // β
const locked = Door.transition(open, "lock"); // β Can't lock an open doorEffect System Annotations
Compile-time side-effect tracking.
import { pure, io, async, assertPure } from "@typesugar/type-system";
@pure
function add(a: number, b: number): number {
return a + b;
}
@io
function log(msg: string): void {
console.log(msg);
}
// Verify purity at compile time
assertPure(() => add(1, 2)); // β
assertPure(() => log("hello")); // β Compile error: log has IO effectAPI Reference
HKT
$<F, A>β Apply type constructor F to type AKindβ Base type for type constructorsArrayF,PromiseF,SetF,MapFβ Built-in type-level functions
Existential Types
Exists<W>β Existential type with witness WpackExists,useExists,mapExistsβ OperationsShowable,Comparable,Serializableβ Common witnesses
Refinement Types
Refined<Base, R>β Refined typerefinement(predicate, name)β Create refinementPositive,NonNegative,Int,Byte,Portβ Number refinementsNonEmpty,Email,Url,Uuidβ String refinements
Type-Level Arithmetic
Add,Sub,Mul,Div,Mod,Powβ OperationsLt,Lte,Gt,Gte,Eqβ ComparisonsInc,Dec,Negate,Absβ Unary operations
Length-Indexed Arrays
Vec<T, N>β Array of T with exactly N elementsVec.from(arr)β Create from array (validates length at runtime)Vec.empty()β Create empty Vec<T, 0>Vec.fill(value, n)β Create Vec<T, N> filled with valueVec.cons(head, tail)β Prepend element (N+1)Vec.snoc(init, last)β Append element (N+1)Vec.concat(a, b)β Concatenate (Add<N, M>)Vec.head(v),Vec.last(v)β First/last element (error on empty)Vec.tail(v),Vec.init(v)β Rest/prefix (Sub<N, 1>)Vec.zip(a, b)β Zip two vectors of same lengthVec.length(v)β Get length as literal type N
Opaque Types
Opaque<Base, Brand>β Opaque typeOpaqueModuleβ Module with make/unwrapopaqueModule(options)β Create opaque module
Phantom Types
Phantom<State, Data>β Phantom-typed valuecreateStateMachine()β State machine buildertransition(state, event)β Type-safe transition
Effects
@pure,@io,@asyncβ Effect annotationsassertPure(fn)β Verify purity at compile timePure,IO,Asyncβ Effect types
License
MIT
