Repository navigation
Types
Declare the data required by your contracts. Built-ins are always available and need no use or depends on.
| Type | Meaning |
|---|---|
Text |
Text values |
Number |
Numeric values; no separately declared integer primitive |
Boolean |
true or false
|
List<T> |
A list with element type T
|
Nothing |
An explicitly valueless callable result |
Do not redefine these built-in names or replace them with import aliases. Nothing is for a complete callable result, including an alias to it. It is not a field/parameter type or a member of a tuple, list, optional or union.
main.expec
type ShoppingCart {
itemsCount: Number
}
type PlayerStateSnapshot {
characterPosition: [Number, Number]
shoppingCart: ShoppingCart
}
examples {
fixture start: PlayerStateSnapshot = PlayerStateSnapshot {
characterPosition: [0, 0],
shoppingCart: ShoppingCart { itemsCount: 0 },
}
}Records have nominal identity: two distinct record declarations do not become interchangeable merely because their fields match. A record literal can state its type, or receive an unambiguous expected record type from its context. Unknown, duplicate or missing required fields are errors.
A suffix ? makes a type optional. An optional record field may be omitted. It does not permit silently using an optional value where a nonoptional value is required.
main.expec
type Book {
title: Text
subtitle: Text?
available: Boolean = true
}
examples {
fixture dune: Book = Book { title: "Dune", available: true }
}subtitle is optional, so the fixture omits it. available has an authored default, but a fixture must still supply explicit data for every nonoptional field: it does not inherit or evaluate type defaults. Ordinary record expressions and generated defaults have their own checked/output rules. Record-field defaults do not implicitly see sibling fields. See Fixtures.
main.expec
type Pair<T> = [T, T]
type Position = Pair<Number>
type Box<T> {
value: T
}
type BookTitle = Text
type State {
position: Position
labels: List<Box<BookTitle>>
}type Name = ... is a transparent alias. type Name { ... } declares a record. Generic parameters are scoped to their declaring type. Supply the correct number of arguments; there is no inference of omitted type arguments. Generic applications are checked without silently changing their argument types.
Record recursion can be meaningful; a transparent alias cycle is invalid.
main.expec
type Position = [Number, Number]
type Mode = "preview" | "live"
type Selection = "small" | 0 | -1 | true
type Settings {
position: Position
mode: Mode
label: (Text | Number)?
}A tuple is a nonempty ordered type list and requires the exact number and order of values. A tuple is not automatically a List.
A union A | B accepts either alternative. Optionality binds before union: Text | Number? differs from (Text | Number)?. Literal types restrict a value to specific text, numbers or Booleans. An expression such as "preview" is a Text value; its type context can require that particular literal.
main.expec
opaque type Token
opaque type Handle<T>
function resume(token: Token) returns Nothing
function obtain() returns Handle<Text>An opaque declaration names a type without exposing record fields. It is not an empty record and cannot be constructed as a record literal. Code output support for such a type depends on the chosen profile.
Related: Expressions and operators · Domain errors · Output support
Home · Keyword index · Released source 36748015 · pr-44 package
Reference edition: October 7, 2026. Checked language examples do not establish implemented runtime behavior.