Supported TypeScript Types
Autoswag uses the TypeScript compiler API to understand your types and convert them to OpenAPI schemas.
Primitives
Basic Types
type Email = string // → { "type": "string" }
type IsValid = boolean // → { "type": "boolean" }Literal Types
type Status = 'active' // → { "type": "string", "enum": ["active"] }
type Code = 200 // → { "type": "number", "enum": [200] }Any and Unknown
type MyAny = any // → { } (empty schema, allows anything)
type MyUnknown = unknown // → { } (empty schema)WARNING
any and unknown types generate empty schemas with no validation. Use specific types when possible.
Objects
Interfaces
interface User {
id: string
name: string
email?: string // Optional
}Generated OpenAPI:
{
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"email": { "type": "string" }
},
"required": ["id", "name"]
}Type Aliases
type Point = {
x: number
y: number
}Works identically to interfaces.
Nested Objects
interface Address {
street: string
city: string
country: string
}
interface User {
name: string
address: Address
}Generated OpenAPI:
{
"type": "object",
"properties": {
"name": { "type": "string" },
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"country": { "type": "string" }
},
"required": ["street", "city", "country"]
}
},
"required": ["name", "address"]
}Index Signatures
interface Dictionary {
[key: string]: number
}Generated OpenAPI:
{
"type": "object",
"additionalProperties": {
"type": "number"
}
}Readonly Properties
interface User {
readonly id: string // Treated as required, no special OpenAPI handling
name: string
}INFO
OpenAPI doesn't have a readonly concept. The property is just required.
Arrays
Array Syntax
// → { "type": "array", "items": { "type": "string" } }
type Tags = string[]
// → { "type": "array", "items": { "type": "number" } }
type Numbers = Array<number>
// → { "type": "array", "items": { "$ref": "#/components/schemas/User" }}
type Users = User[]Nested Arrays
type Matrix = number[][] // → array of arrays
type Complex = User[][] // → array of array of UserTuples
Fixed-length arrays with specific types for each position.
type Pair = [string, number]OpenAPI 3.1 (prefixItems):
{
"type": "array",
"prefixItems": [{ "type": "string" }, { "type": "number" }],
"minItems": 2,
"maxItems": 2
}OpenAPI 3.0 (oneOf workaround):
{
"type": "array",
"items": {
"oneOf": [{ "type": "string" }, { "type": "number" }]
}
}Unions
Multiple possible types, separated by |.
Union of same type Primitives
// → { "type": "string", "enum": ["pending", "active", "inactive"] }
type Status = 'pending' | 'active' | 'inactive'
// → { "type": "number", "enum": [200, 404, 500] }
type Code = 200 | 404 | 500Union of Objects
interface Success {
status: 'success'
data: string
}
interface Error {
status: 'error'
message: string
}
type Response = Success | ErrorGenerated OpenAPI:
{
"oneOf": [
{
"type": "object",
"properties": {
"status": { "type": "string", "enum": ["success"] },
"data": { "type": "string" }
},
"required": ["status", "data"]
},
{
"type": "object",
"properties": {
"status": { "type": "string", "enum": ["error"] },
"message": { "type": "string" }
},
"required": ["status", "message"]
}
]
}Optional via Union with Undefined
interface Example {
optional1: string | undefined // Same as string?
optional2?: string // Preferred syntax
}Both generate the same OpenAPI (non-required property).
Nullable Types
interface Example {
nullableString: string | null
}OpenAPI 3.1:
{
"type": ["string", "null"]
}OpenAPI 3.0:
{
"type": "string",
"nullable": true
}Intersections
Combine multiple types with &.
interface Named {
name: string
}
interface Aged {
age: number
}
type Person = Named & Aged
// Equivalent to:
// interface Person {
// name: string
// age: number
// }Generated OpenAPI:
{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "number" }
},
"required": ["name", "age"]
}WARNING
Autoswag handles only objects intersections.
WARNING
If an object intersection contains a property defined in both objects, Autoswag uses the one from the object listed first. Example:
// → { "type": "string" }
type A = { id: string } & { id: number }
// → { "type": "number" }
type A = { id: number } & { id: string }Enums
String Enums
enum Status {
Pending = 'pending',
Active = 'active',
Inactive = 'inactive',
}Generated OpenAPI:
{
"type": "string",
"enum": ["pending", "active", "inactive"]
}Numeric Enums
enum HttpStatus {
OK = 200,
NotFound = 404,
ServerError = 500,
}Generated OpenAPI:
{
"type": "number",
"enum": [200, 404, 500]
}Auto-Incrementing Enums
enum Order {
First, // 0
Second, // 1
Third, // 2
}Generated OpenAPI:
{
"type": "number",
"enum": [0, 1, 2]
}Const Enums
const enum Direction {
Up = 'up',
Down = 'down',
}Works the same as regular enums.
Records
Key-value maps with typed keys and values.
Record Type
type StringMap = Record<string, number>
// Equivalent to:
// interface StringMap {
// [key: string]: number
// }Generated OpenAPI:
{
"type": "object",
"additionalProperties": {
"type": "number"
}
}Record with Object Values
type UserMap = Record<string, User>Generated OpenAPI:
{
"type": "object",
"additionalProperties": {
"$ref": "#/components/schemas/User"
}
}Record with Literal Keys
type Config = Record<'development' | 'production', string>
// Expands to:
// interface Config {
// development: string
// production: string
// }Generics
Generic Types
interface Response<T> {
data: T
status: number
}
type UserResponse = Response<User>
// Expands to:
// interface UserResponse {
// data: User
// status: number
// }INFO
Generics are resolved at the point of use. The generic type itself isn't exported to OpenAPI.
Limitations
Not Supported
These TypeScript features don't convert to OpenAPI:
- Function types - Methods on interfaces are ignored
- Unresolved conditional types -
T extends U ? X : Y - Template literal types -
`prefix-${string}`(resolves to string) - Symbols -
symboltype - Classes - Use interfaces instead
Circular References
Circular types must use the @component tag:
/**
* @component TreeNode
*/
interface TreeNode {
value: string
children: TreeNode[] // Circular reference
}Without @component, circular references throw an error.