Magic Types
"Magic Types" is a shorthand for Swagger schemas: instead of a verbose schema object, you write one string that captures the type, an optional format, an example, and whether the field is required.
On Express, Magic Types describe swaggerModel schemas and _<verb>Swagger types,
feeding OpenAPI and type generation. On Bun/Elysia, the same
DSL is accepted inside a class's _<verb>Swagger (requestBody, responses,
parameters) and the models registry, and expanded
into the native OpenAPI document. Either way Magic Types drive documentation only,
not request validation (Express uses express-validator, Elysia uses
TypeBox). Type generation is Express-only.
Try it
Type a Magic Type below; the OpenAPI schema and TypeScript type update as you go:
type[::format][|example][!|?] · arrays [] · refs @Model
{
"type": "string",
"format": "email",
"example": "john@example.com!"
}required follows defaultRequiredValueForModels
type T = string;
Syntax
type[::format][|example][!|?]
- type: A base data type or a reference to another model. Base types are
string,number,integer,boolean,array,object,Date, andObjectId. String formats aredate,date-time,password,byte,binary. - ::format: (Optional) The format for validation (email, date-time, etc.).
- |example: (Optional) An example value for documentation.
- !: (Optional) Marks the field as required (overrides default).
- ?: (Optional) Marks the field as optional (overrides default).
Examples
| Magic Type | Description | Swagger Equivalent |
|---|---|---|
string | A simple string | { type: "string" } |
string::email | A string with email format | { type: "string", format: "email" } |
number! | A required number | { type: "number" }, required: true |
boolean? | An optional boolean | { type: "boolean" }, required: false |
string|John Doe | A string with an example | { type: "string", example: "John Doe" } |
string::email|john@example.com | Email with example | { type: "string", format: "email", example: "john@example.com" } |
Arrays
Append [] for an array.
| Magic Type | Description | Swagger Equivalent |
|---|---|---|
string[] | Array of strings | { type: "array", items: { type: "string" } } |
number[]! | Required array of numbers | { type: "array", items: { type: "number" } }, required: true |
@User[] | Array of User models | { type: "array", items: { $ref: "#/components/schemas/User" } } |
Model References
Reference another schema with @ followed by its name.
| Magic Type | Description | Swagger Equivalent |
|---|---|---|
@User | Reference to User model | { $ref: "#/components/schemas/User" } |
@User! | Required User reference | { $ref: "#/components/schemas/User" }, required: true |
@User? | Optional User reference | { $ref: "#/components/schemas/User" }, required: false |
Custom Types
Define reusable types in config.customTypes, then use them like any base type.
Configuration
// efesto config
customTypes: {
ObjectId: "string",
Date: { type: "string", format: "date-time" },
Price: { type: "number", format: "float" }
}
Usage
properties: {
id: "ObjectId",
createdAt: "Date",
cost: "Price"
}
A complete model
swaggerModel = {
modelName: "User",
schemas: [
{
name: "User",
properties: {
id: "ObjectId", // Custom type
username: "string!", // Required string
email: "string::email!", // Required email
age: "number?", // Optional number
tags: "string[]", // Array of strings
profile: "@UserProfile", // Reference to another model
createdAt: "Date", // Custom type
},
},
],
};
Nullable Fields
If you have configured defaultNullableOnOptionalFields: true, using the ? operator will also mark the field as nullable: true in the generated Swagger schema.
// With defaultNullableOnOptionalFields: true
"string?";
// Becomes: { type: "string", nullable: true } (and removed from required list)