Unions, literais e enums
Os três kinds de “escolha” no Sapphire — union, literal, enum — permitem expressar “um destes shapes” ou “um destes valores”. Todos vivem sob o namespace a.type() porque são construtores, não primitivos autônomos. Esta página cobre a construção deles, seus tipos inferidos e como cada adapter os materializa.
Union
a.type().union([f1, f2, ...]) aceita qualquer valor que faça parse com sucesso contra ao menos um dos fields internos. O tipo de saída é a união dos tipos de saída internos.
const id = a.type().union([a.string(), a.number()])
type Id = Infer<typeof id>
// Id = string | number
Mapeamento de adapter:
| Adapter | Saída |
|---|---|
| Mongo | Schema.Types.Mixed (sem estreitamento em runtime — a ressalva está documentada). |
| JSON Schema | oneOf: [...]. |
| Drizzle | coluna jsonb (Postgres) / fallback por dialeto. |
Literal
a.type().literal(value) casa exatamente um valor string, number ou boolean. O tipo de saída é estreitado para aquele literal.
const kind = a.type().literal('admin')
type Kind = Infer<typeof kind>
// Kind = 'admin'
Enum
a.type().enum(values) aceita ou um array readonly de literais (use as const) ou um objeto enum do TypeScript.
const role = a.type().enum(['admin', 'editor', 'viewer'] as const)
type Role = Infer<typeof role>
// Role = 'admin' | 'editor' | 'viewer'
Com um enum do TS:
enum Status {
Active = 1,
Inactive = 2,
}
const status = a.type().enum(Status)
// _output is Status (a numeric union); reverse mappings ('1','2' → name)
// generated by TS are filtered before being baked into the IR.
Enums numéricos do TS compilam para { Active: 1, Inactive: 2, '1': 'Active', '2': 'Inactive' }. O extractEnumValues do Sapphire descarta chaves que casam com /^\d+$/, então apenas a direção direta chega à IR — valores string NÃO são aceitos como membros de um enum numérico.
Armadilhas
[!WARNING]
literal('admin')eenum(['admin'] as const)têm o mesmo_output. Para um único valor a distinção é cosmética — escolha pela intenção. Useliteralquando o valor é uma tag (discriminante numa union discriminada, o campotypede uma ferramenta MCP); useenumquando o que importa é a pertinência e você espera fazer a lista crescer.
[!WARNING] Sempre passe
as constparaenum(...). Sem ele,['admin','editor']se alarga parastring[]e você obteráRole = stringem vez da união estreitada.as constpreserva os tipos literais de ponta a ponta.
Relacionados
- Fields e modificadores — a referência do construtor
a.type(). - Inferindo tipos.
- Receitas → Compartilhar tipos com o frontend.