# Enums

An enum is a closed list of named alternatives. Variants are always written
with their enum's name.

```jadpo
type TicketStatus = Enum {
    open
    waiting
    closed
}

function reopen() -> TicketStatus {
    return TicketStatus.open
}
```

A variant can carry its own fields, which makes an enum a tagged union: each
value is exactly one variant and has only that variant's fields.

```jadpo
type PaymentOutcome = Enum {
    pending
    paid: {
        receipt_id: ReceiptId
        paid_at: Instant
    }
    declined: {
        reason: DeclineReason
    }
}

function declined_payment(reason: DeclineReason) -> PaymentOutcome {
    return PaymentOutcome.declined {
        reason: reason
    }
}

function label(outcome: PaymentOutcome) -> OutcomeLabel {
    return match outcome {
        PaymentOutcome.pending -> "pending"
        PaymentOutcome.paid -> "paid"
        PaymentOutcome.declined -> "declined"
    }
}
```

The only way to read a variant's fields is to `match` on it. Payload fields
have field types too, written `PaymentOutcome.declined.reason`.

An enum can't be created from text: `TicketStatus("open")` is an error.
Text from outside, such as a request body, becomes a variant only as it is
read and checked on the way in. In JSON a plain variant is its name as a
string (`"open"`), and a variant with fields is an object with a `tag`
naming the variant, plus its fields.

Enums have no methods or display labels. A variant is a name, or a name with
a block of its fields; one given a label, `open: "Open"`, is
`type.enum_label`. Wording for people comes from translations: a domain's
language files can give each value of an enum a wording, which a template
then writes out ([Enums with wording](enums-with-wording.md)).
