type Name = Target gives an existing type another source name.
type UserId = u64
type Users = []User
type Handler = fn(Request) -> Response ! HttpErrorAlias 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) -> boolArguments 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 // errorUse 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 = u64OrderId, 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 | stringWithout 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.