[ PROMPT_NODE_25015 ]
Openapi To Typescript
[ SKILL_DOCUMENTATION ]
# OpenAPI to TypeScript
Converts OpenAPI 3.0 specifications to TypeScript interfaces and type guards.
**Input:** OpenAPI file (JSON or YAML)
**Output:** TypeScript file with interfaces and type guards
## When to Use
- "generate types from openapi"
- "convert openapi to typescript"
- "create API interfaces"
- "generate types from spec"
## Workflow
1. Request the OpenAPI file path (if not provided)
2. Read and validate the file (must be OpenAPI 3.0.x)
3. Extract schemas from `components/schemas`
4. Extract endpoints from `paths` (request/response types)
5. Generate TypeScript (interfaces + type guards)
6. Ask where to save (default: `types/api.ts` in current directory)
7. Write the file
## OpenAPI Validation
Check before processing:
```
- Field "openapi" must exist and start with "3.0"
- Field "paths" must exist
- Field "components.schemas" must exist (if there are types)
```
If invalid, report the error and stop.
## Type Mapping
### Primitives
| OpenAPI | TypeScript |
|-------------|--------------|
| `string` | `string` |
| `number` | `number` |
| `integer` | `number` |
| `boolean` | `boolean` |
| `null` | `null` |
### Format Modifiers
| Format | TypeScript |
|---------------|-------------------------|
| `uuid` | `string` (comment UUID) |
| `date` | `string` (comment date) |
| `date-time` | `string` (comment ISO) |
| `email` | `string` (comment email)|
| `uri` | `string` (comment URI) |
### Complex Types
**Object:**
```typescript
// OpenAPI: type: object, properties: {id, name}, required: [id]
interface Example {
id: string; // required: no ?
name?: string; // optional: with ?
}
```
**Array:**
```typescript
// OpenAPI: type: array, items: {type: string}
type Names = string[];
```
**Enum:**
```typescript
// OpenAPI: type: string, enum: [active, draft]
type Status = "active" | "draft";
```
**oneOf (Union):**
```typescript
// OpenAPI: oneOf: [{$ref: Cat}, {$ref: Dog}]
type Pet = Cat | Dog;
```
**allOf (Intersection/Extends):**
```typescript
// OpenAPI: allOf: [{$ref: Base}, {type: object, properties: ...}]
interface Extended extends Base {
extraField: string;
}
```
## Code Generation
### File Header
```typescript
/**
* Auto-generated from: {source_file}
* Generated at: {timestamp}
*
* DO NOT EDIT MANUALLY - Regenerate from OpenAPI schema
*/
```
### Interfaces (from components/schemas)
For each schema in `components/schemas`:
```typescript
export interface Product {
/** Product unique identifier */
id: string;
/** Product title */
title: string;
/** Product price */
price: number;
/** Created timestamp */
created_at?: string;
}
```
- Use OpenAPI description as JSDoc
- Fields in `required[]` have no `?`
- Fields outside `required[]` have `?`
### Request/Response Types (from paths)
For each endpoint in `paths`:
```typescript
// GET /products - query params
export interface GetProductsRequest {
page?: number;
limit?: number;
}
// GET /products - response 200
export type GetProductsResponse = ProductList;
// POST /products - request body
export interface CreateProductRequest {
title: string;
price: number;
}
// POST /products - response 201
export type CreateProductResponse = Product;
```
Naming convention:
- `{Method}{Path}Request` for params/body
- `{Method}{Path}Response` for response
### Type Guards
For each main interface, generate a type guard:
```typescript
export function isProduct(value: unknown): value is Product {
return (
typeof value === 'object' &&
value !== null &&
'id' in value &&
typeof (value as any).id === 'string' &&
'title' in value &&
typeof (value as any).title === 'string' &&
'price' in value &&
typeof (value as any).price === 'number'
);
}
```
Type guard rules:
- Check `typeof value === 'object' && value !== null`
- For each required field: check `'field' in value`
- For primitive fields: check `typeof`
- For arrays: check `Array.isArray()`
- For enums: check `.includes()`
### Error Type (always include)
```typescript
export interface ApiError {
status: number;
error: string;
detail?: string;
}
export function isApiError(value: unknown): value is ApiError {
return (
typeof value === 'object' &&
value !== null &&
'status' in value &&
typeof (value as any).status === 'number' &&
'error' in value &&
typeof (value as any).error === 'string'
);
}
```
## $ref Resolution
When encountering `{"$ref": "#/components/schemas/Product"}`:
1. Extract the schema name (`Product`)
2. Use the type directly (don't resolve inline)
```typescript
// OpenAPI: items: {$ref: "#/components/schemas/Product"}
// TypeScript:
items: Product[] // reference, not inline
```
## Complete Example
**Input (OpenAPI):**
```json
{
"openapi": "3.0.0",
"components": {
"schemas": {
"User": {
"type": "object",
"properties": {
"id": {"type": "string", "format": "uuid"},
"email": {"type": "string", "format": "email"},
"role": {"type": "string", "enum": ["admin", "user"]}
},
"required": ["id", "email", "role"]
}
}
},
"paths": {
"/users/{id}": {
"get": {
"parameters": [{"name": "id", "in": "path", "required": true}],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {"$ref": "#/components/schemas/User"}
}
}
}
}
}
}
}
}
```
**Output (TypeScript):**
```typescript
/**
* Auto-generated from: api.openapi.json
* Generated at: 2025-01-15T10:30:00Z
*
* DO NOT EDIT MANUALLY - Regenerate from OpenAPI schema
*/
// ============================================================================
// Types
// ============================================================================
export type UserRole = "admin" | "user";
export interface User {
/** UUID */
id: string;
/** Email */
email: string;
role: UserRole;
}
// ============================================================================
// Request/Response Types
// ============================================================================
export interface GetUserByIdRequest {
id: string;
}
export type GetUserByIdResponse = User;
// ============================================================================
// Type Guards
// ============================================================================
export function isUser(value: unknown): value is User {
return (
typeof value === 'object' &&
value !== null &&
'id' in value &&
typeof (value as any).id === 'string' &&
'email' in value &&
typeof (value as any).email === 'string' &&
'role' in value &&
['admin', 'user'].includes((value as any).role)
);
}
// ============================================================================
// Error Types
// ============================================================================
export interface ApiError {
status: number;
error: string;
detail?: string;
}
export function isApiError(value: unknown): value is ApiError {
return (
typeof value === 'object' &&
value !== null &&
'status' in value &&
typeof (value as any).status === 'number' &&
'error' in value &&
typeof (value as any).error === 'string'
);
}
```
## Common Errors
| Error | Action |
|-------|--------|
| OpenAPI version != 3.0.x | Report that only 3.0 is supported |
| $ref not found | List missing refs |
| Unknown type | Use `unknown` and warn |
| Circular reference | Use type alias with lazy reference |
Source: claude-code-templates (MIT). See About Us for full credits.