Repository navigation
Named Types and Unions
type introduces a distinct identity backed by a type expression. It is not a
transparent alternate spelling.
type Meters = Float
let $near: Meters = 3
let $far = Meters(4)
let $total = $near + $far
echo $total $total.type Float($total)
7.0 Meters 7.0
Annotations wrap compatible values; explicit construction can do the same. Unwrapping is explicit. Same-type numeric arithmetic preserves the named type; mixing named types or a named and unnamed number needs a deliberate conversion. Inherited methods retain their own declared results.
Nested definitions such as type RouteLength = Meters are allowed. Named arrays,
hashes, and structs inherit their underlying operations while keeping identity.
Items yielded from named collections are the underlying collection's items.
let $label: Integer | String = 7
$label = "seven"
let $maybe: Integer | ()
echo $label $maybe
type Selection = Integer | String | ()
let $selected: Selection
echo $selected.type
seven ()
Selection
An existing union-member match preserves the value. Otherwise implicit wrapping
or Integer-to-Float promotion must have one unambiguous result. Unions admitting
() default to unit; others need initialization. A named union remains a named
value, including when it contains unit.
A named union can define methods without attaching them to every member globally. An annotation or explicit conversion selects that interface. Exact type narrowing selects the concrete member's methods inside a branch.
Marked error unions are especially useful for library error interfaces. They keep
the concrete error payload's .type while exposing the union's selected methods.
Normal named unions retain their nominal .type. See
Errors and cleanup for propagation and handling.
error struct BadLabel { pub detail: String }
error struct NoCapacity { pub detail: String }
type PackingError = BadLabel | NoCapacity
fn PackingError::message(): String
{
match $self.type
{
BadLabel => { "label: " + $self.detail }
NoCapacity => { "capacity: " + $self.detail }
}
}
try { let $problem: PackingError = BadLabel(detail: "missing postcode") }
catch ($problem: PackingError) { echo $problem.message $problem.type }
label: missing postcode BadLabel
Recursive aliases are rejected. Struct recursion through optional or collection fields can model linked structures without requiring an impossible fully initialized cycle.
Related: Conversions · Function types · Errors
Begin here
Values and expressions
- Language basics
- Variables and scope
- Numbers and logic
- Strings and paths
- Arrays
- Hash maps
- Ranges and iteration
- Control flow
- Match and type guards
Functions and types
- Functions and calls
- Closures and function types
- Methods and properties
- Structs
- Enums
- Named types and unions
- Conversions
- Types and properties
Shell and modules
- Pipelines
- Pipeline splits
- Pipeline formats
- Commands and exit status
- Redirection
- Environment and exported variables
- Modules and visibility
- Nested modules and directory packages
- Conditional imports and declarations
- Errors and cleanup
- Supervised processes and terminals
Library guides
- Standard library
- The implicit prelude
- Bytes, files, readers, and writers
- Explicit item streams
- JSON documents and typed mapping
- Sockets, DNS, and TLS
- HTTP clients
- HTTP servers
- Framing, server-sent events, and JSON-RPC
- Terminal colors, styles, and geometry
- Build an application console
Interactive use