This example demonstrates how to use oax to generate fully type-safe API clients from OpenAPI specifications. We'll be using the famous Petstore API to showcase the power of automatic code generation and TypeScript type safety.
- ✅ Type-Safe API Calls: Generated client methods with full TypeScript support
- ✅ Parameter Validation: TypeScript ensures you pass the correct parameters
- ✅ Response Type Safety: Know exactly what data you'll receive back
- ✅ Runtime Error Handling: Proper error handling with typed responses
- ✅ Developer Experience: IntelliSense, autocomplete, and compile-time checks
-
Install Dependencies
pnpm install
-
Start the Development Server
pnpm run dev
-
Open Your Browser Navigate to the localhost URL shown in your terminal (typically http://localhost:5173)
pnpm run dev- Start development serverpnpm run build- Build for productionpnpm run lint- Lint code with Biomepnpm run format- Format code with Biomepnpm run check- Run Biome checks (lint + format)pnpm run typecheck- Type check with TypeScript
The API client is generated from the Petstore OpenAPI spec:
# This command was used to generate the client
node ../../packages/cli/dist/index.js generate \
-i https://petstore.swagger.io/v2/swagger.json \
-o src/api/client.tsThis creates a fully typed client in src/api/client.ts with:
- Type-safe operation methods
- Parameter validation schemas
- Response type definitions
- Full IntelliSense support
import { createClient } from "@oax/core";
import { operations } from "./api/client";
// Create typed client - TypeScript knows all available methods!
const client = createClient("https://petstore.swagger.io/v2", operations);
// Type-safe API calls
const pet = await client.getPetById({ petId: 1 });
// ^-- TypeScript knows the exact shape of this response
// TypeScript will catch errors at compile time:
// await client.getPetById({ wrongParam: 1 }); // ❌ Compile error!
// await client.getPetById(); // ❌ Missing required parameter!The generated client provides several levels of type safety:
// ✅ Correct usage - TypeScript is happy
await client.getPetById({ petId: 123 });
// ❌ Wrong parameter name - TypeScript error
await client.getPetById({ id: 123 });
// ❌ Wrong parameter type - TypeScript error
await client.getPetById({ petId: "not-a-number" });
// ❌ Missing required parameter - TypeScript error
await client.getPetById();const pet = await client.getPetById({ petId: 1 });
// ✅ TypeScript knows these properties exist
console.log(pet.name);
console.log(pet.status); // "available" | "pending" | "sold"
console.log(pet.category?.name);
// ❌ TypeScript prevents accessing non-existent properties
console.log(pet.nonExistentProperty); // Compile error!Your IDE will provide:
- Method suggestions as you type
- Parameter hints and validation
- Return type information
- Documentation from the OpenAPI spec
examples/basic/
├── src/
│ ├── api/
│ │ └── client.ts # Generated API client
│ ├── App.tsx # Main React component with API integration
│ ├── App.css # Styling
│ └── main.tsx # React app entry point
├── package.json # Project dependencies
└── README.md # This file
- Makes actual HTTP requests to petstore.swagger.io
- Handles loading states and errors
- Demonstrates CORS-enabled API calls
- Compile-time safety: Catch errors before runtime
- IntelliSense: Full autocomplete for API methods and data
- Refactoring safety: Change detection across your codebase
- Documentation: Method signatures serve as living documentation
- Zero configuration: Works out of the box
- Fast feedback: Immediate error detection in your IDE
- Predictable: Generated code follows consistent patterns
- Maintainable: Easy to update when the API changes
try {
const pet = await client.getPetById({ petId: 999999 });
setPet(pet);
} catch (error) {
// Handle API errors (404, 500, network issues, etc.)
setError(error.message);
}const client = createClient(
"https://petstore.swagger.io/v2",
operations,
{
headers: {
'Authorization': 'Bearer your-token',
'X-Custom-Header': 'value'
}
}
);If the API changes, simply regenerate the client:
# Update the generated client
node ../../packages/cli/dist/index.js generate \
-i https://petstore.swagger.io/v2/swagger.json \
-o src/api/client.ts
# TypeScript will immediately show you what changed!Try modifying this example to:
- Add more API operations (create pet, update pet, etc.)
- Implement form validation using the generated schemas
- Add request/response interceptors
- Handle different response formats
- Integrate with your favorite state management library
Happy coding with type safety! 🎉