Skip to content

Aliases

Declare transparent generic synonyms or distinct nominal wrappers.

Updated View as Markdown

type Name = Target gives an existing type another source name.

type UserId = u64
type Users = []User
type Handler = fn(Request) -> Response ! HttpError

Alias names use PascalCase.

Transparency

A normal alias does not introduce a new type identity.

type UserId = u64

fn load(id: UserId): void {}

raw: u64 = 42
load(raw)

UserId and u64 resolve to the same type. The alias improves vocabulary and can shorten a complex type, but it does not prevent values from mixing.

Aliases are recursively expanded. An alias of another alias eventually resolves to the underlying type.

Generics

Aliases can have type parameters.

type Pair[A, B] = (A, B)
type Lookup[T] = Map[string, T]
type Predicate[T] = fn(T) -> bool

Arguments use square brackets.

entry: Pair[string, int] = ("port", 8080)

Every use must provide the declared arity. Each substitution is independent; using Pair[int, bool] does not affect Pair[float, string].

Cycles

Aliases must eventually expand to a real type. Direct and indirect alias cycles are compile errors.

type First = Second
type Second = First // error

Use a struct, enum, or managed container when the domain is genuinely recursive.

Distinct aliases

Prefix an alias with distinct to introduce nominal identity while retaining an underlying representation.

distinct type OrderId = u64
distinct type CustomerId = u64

OrderId, CustomerId, and u64 are different types. A value of the representation type does not implicitly satisfy a distinct alias.

fn take_order(id: OrderId): void {}

raw: u64 = 42
// take_order(raw) is a type error.

Construction and conversion must go through an explicitly supported function, method, or representation conversion. This makes domain crossings visible.

Methods

A distinct alias can have its own receiver-prefix methods.

distinct type UserName = string

fn UserName.is_reserved(self): bool {
    return false
}

Its methods do not become methods on every value of the representation type.

Transparent aliases cannot carry an independent method identity because they resolve to their target.

Unions

A distinct alias is useful when two anonymous unions have the same member types but different domain meanings.

distinct type InputValue = int | string
distinct type OutputValue = int | string

Without distinct, both aliases would expand to the same canonical anonymous union.

API use

Choose:

  • a transparent alias for readability and abbreviation;
  • a distinct alias for domain separation with a known representation;
  • a struct when fields, construction, evolution, and behavior deserve an explicit nominal product type;
  • an enum when the domain is a named set of alternatives.

Changing a transparent alias target changes every use after expansion. Changing a distinct representation also affects conversion and ABI concerns, even though the nominal identity remains.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close