Optionals
Generated Markdown for references/concept_optionals.md.
Open book page Back to the skill graph
# Optionals
_Values that may be present or absent — the none literal and the ? type suffix._
An **optional** is a value that may be present or absent. The literal `none` represents absence; a `?` suffix on a type makes its values optional. Together they let a field be omitted, a function return no answer, or a slot be cleared explicitly.
## Optional types
Suffix any type with `?` to make it optional. A `T?` field accepts either a `T` value or the literal `none`. A field without `?` is required and rejects `none`.
```wcl
type Profile {
name: utf8 // required
bio: utf8? // optional — may be none
age: u32? // optional
}
complete = Profile { name: "Alice", bio: "Author.", age: 34u32 }
partial = Profile { name: "Bob", bio: none, age: none }
```
## The none literal
`none` is the value that fills an absent optional. It is also the result of builtins that do not return a useful value (`error`, `panic`, `assert`) — those have type `none` and cannot meaningfully be used in a value position.
```wcl
note: utf8? = none
```
## Working with optionals
Pattern-match an optional to handle the two cases. The `if let` shorthand is convenient when you only care about the present case. See [match](../references/concept_match_expr.md) and [if let](../references/concept_if_let.md).
```wcl
display = match maybe_name {
none => "anonymous",
n => n,
}
shout = if let n = maybe_name {
to_upper(n)
} else {
"ANONYMOUS"
}
```
## Defaults with ??
The `??` operator picks the left value unless it is `none`, in which case it returns the right side — the concise way to give an optional a default. It chains left-to-right and binds looser than every other operator, and the right side only evaluates when needed.
```wcl
width = box.width ?? 480.0
theme = page.theme ?? site.theme ?? :nord
label = trim(raw_label) ?? "untitled" // (trim(raw_label)) ?? "untitled"
```
> [!NOTE]
> **Optionals vs unions**
> Use T? when the only states are present and absent. When absence carries information (a reason, a fallback, multiple shapes), reach for a union instead.
## Examples
### Optional fields and the ?? default
A `?` suffix makes a field optional; `??` supplies a fallback when it is `none`.
```wcl
type Profile {
name: utf8 // required
bio: utf8? // optional — may be none
}
partial = Profile { name: "Bob", bio: none }
theme = page.theme ?? site.theme ?? :nord
```
**Expected:** `partial.bio` is `none`; `theme` falls back to `site.theme`, then `:nord`.
## Related
- [Unions](../references/concept_unions.md)
- [match](../references/concept_match_expr.md)
- [if let](../references/concept_if_let.md)
[← Back to SKILL.md](../SKILL.md)