Enum
Enum scalar type that restricts values to a predefined set of options
Basic Usage
import { s } from "viborm";
s.enum(["PENDING", "ACTIVE", "SUSPENDED"]); // Required enum
s.enum(["PENDING", "ACTIVE"]).nullable(); // Enum | null
s.enum(["USER", "ADMIN"]).default("USER"); // Default (must be in enum)
Enums support .nullable(), .array(), .default(), and .map() — but not .id(), .unique(), or .schema(). See the support matrix.
Naming Enums for Reuse
By default, VibORM generates enum type names based on the table and column (e.g., user_status_enum). Use .name() to create a shared enum type that can be reused across multiple tables:
// Define a named enum at the top level
const Status = s.enum(["PENDING", "ACTIVE", "INACTIVE"]).name("status");
// Use it in multiple models - same PostgreSQL enum type
const user = s.model({
id: s.string().id(),
status: Status.default("PENDING"), // Uses "status" enum type
});
const order = s.model({
id: s.string().id(),
status: Status.default("PENDING"), // Same "status" enum type
});
Without .name(), each column would create its own enum type:
user_status_enumfor users.statusorder_status_enumfor orders.status
With .name("status"), both columns share the same status enum type.
Type Inference
The TypeScript type is automatically inferred as a union:
const role = s.enum(["USER", "ADMIN", "MODERATOR"]);
// TypeScript type: "USER" | "ADMIN" | "MODERATOR"
const status = s.enum(["draft", "published", "archived"]).nullable();
// TypeScript type: "draft" | "published" | "archived" | null
Database Behavior
PostgreSQL creates a native ENUM type, named <table>_<column>_enum unless overridden with .name():
CREATE TYPE "users_role_enum" AS ENUM ('USER', 'ADMIN', 'MODERATOR');
CREATE TABLE users (
role "users_role_enum" NOT NULL
);MySQL uses inline ENUM:
CREATE TABLE users (
role ENUM('USER', 'ADMIN', 'MODERATOR') NOT NULL
);SQLite stores as TEXT with check constraint:
CREATE TABLE users (
role TEXT CHECK(role IN ('USER', 'ADMIN', 'MODERATOR')) NOT NULL
);Examples
// User role
const role = s.enum(["USER", "ADMIN", "MODERATOR"]).default("USER");
// Order status
const orderStatus = s
.enum([
"PENDING",
"CONFIRMED",
"PROCESSING",
"SHIPPED",
"DELIVERED",
"CANCELLED",
])
.default("PENDING");
// Content visibility
const visibility = s.enum(["PUBLIC", "PRIVATE", "UNLISTED"]).default("PUBLIC");
// Priority level
const priority = s.enum(["LOW", "MEDIUM", "HIGH", "CRITICAL"]);
Enum vs String
| Aspect | Enum | String |
|---|---|---|
| Type safety | Compile-time restricted | Any string |
| Validation | Database enforced | Needs custom validator |
| Flexibility | Fixed set | Any value |
| Migrations | Requires migration to add values | No migration needed |
Use an enum for a fixed set of values that rarely changes (statuses, roles, tiers) and needs database-level enforcement. Use a string when values change frequently or are user-defined.