Enum Extensions
Generate enums with names and descriptions using OpenAPI extensions
Use OpenAPI extensions and OpenAPI 3.1 enum metadata to generate enums with meaningful names and descriptions.
OpenAPI Schema
Use x-enumNames to assign meaningful names to enum members, and x-enumDescriptions to add JSDoc comments that appear in IDE tooltips.
openapi: '3.1.0'
info:
version: 1.0.0
title: Swagger Petstore
components:
schemas:
MyObject:
type: object
properties:
myEnum:
type: number
enum:
- 1
- 2
- 3
- 4
x-enumNames:
- One
- Two
- Three
- Four
x-enumDescriptions:
- Represents the first value
- Represents the second value
- Represents the third value
- Represents the fourth valueGenerated Output
export const MyEnum = {
/** Represents the first value */
One: 1,
/** Represents the second value */
Two: 2,
/** Represents the third value */
Three: 3,
/** Represents the fourth value */
Four: 4,
} as const;
export type MyEnum = typeof MyEnum[keyof typeof MyEnum];Supported Extensions
Orval recognizes the following extensions:
Enum names:
x-enumNamesx-enumnamesx-enum-varnames
Enum descriptions:
x-enumDescriptionsx-enumdescriptionsx-enum-descriptions
OpenAPI 3.1 const enums
enumGenerationType: 'enum' emits a TypeScript enum declaration. enum
syntax cannot be erased by type stripping, so generated 'enum' output does not
compile under TypeScript 5.8+ erasableSyntaxOnly (e.g. Node's native
TypeScript support). In that environment use const (default) or union — see
the enumGenerationType reference.
OpenAPI 3.1 enum-like schemas using oneOf with const branches can use title, description, and deprecated as member metadata.
components:
schemas:
Status:
oneOf:
- const: PENDING
title: Pending
description: Awaiting manual review
- const: LEGACY
title: Legacy
description: No longer issued
deprecated: trueWith const enum generation, Orval preserves the branch metadata:
export const Status = {
/** Awaiting manual review */
Pending: 'PENDING',
/**
* No longer issued
* @deprecated
*/
Legacy: 'LEGACY',
} as const;
export type Status = typeof Status[keyof typeof Status];When a branch has no title, its member name is derived from the const value and respects output.override.namingConvention.enum.
Unannotated oneOf/const branches retain their existing union output.
Zod
Metadata generates z.enum({ ... }) for Zod 4 and z.nativeEnum({ ... } as const) for Zod 3, while boolean or mixed-type enums remain literal unions and enums without metadata retain their existing output
When metadata produces an enum object (z.enum({ Cat: 'cat', ... })), the generator always emits constant-style key: value pairs and deliberately ignores the enumGenerationType setting. The object is inserted as an object-literal argument, where union ('cat' | 'dog') and enum (Cat = 'cat') output are not valid — either would make the generated code fail to parse. If you need union or enum-style output, apply it to enums without metadata instead.
oneOf/const branches
Annotated oneOf/const branches keep the union-of-literals shape. Each annotated branch carries its title, description and deprecated in .meta(), so the values stay readable at runtime through zod.globalRegistry:
export const Status = zod.union([
zod
.literal('PENDING')
.meta({ title: 'Pending', description: 'Awaiting manual review' }),
zod.literal('LEGACY').meta({
title: 'Legacy',
description: 'No longer issued',
deprecated: true,
}),
]);
Status.options.map((o) => ({ value: o.value, ...zod.globalRegistry.get(o) }));This does not need output.override.zod.generateMeta. Per Zod version:
| Zod version | Output |
|---|---|
| Zod 4 | .meta({ title, description, deprecated }) on each annotated branch |
| Zod 4 Mini | .check(zod.meta({ ... })) on each annotated branch |
| Zod 3 | No registry, so branches keep .describe(description) and title/deprecated are dropped |
Branches that carry only a description keep .describe(). Branches with no metadata stay a bare zod.literal(...), so a spec without member metadata produces the same output as before.