iTranslated by AI
The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
😎
Achieving Type-Safe API Communication with Vue, OpenAPI, and TypeScript
When calling a backend API from the frontend, have you ever faced issues like the following?
- API type definitions going out of sync
- Failing to notice typos in endpoint names
- Inconsistent handling of validation errors
The solution to these issues all at once is OpenAPI (Swagger) and automatic TypeScript code generation.
In this article, I will introduce a setup for achieving secure, type-safe, and reusable API communication using OpenAPI in a Vue 3 + Vite + TypeScript environment.
📦 Technology Stack
| Item | Technology Used |
|---|---|
| Framework | Vue 3 (Composition API) |
| Type Generation | @hey-api/openapi-ts |
| API Specification | OpenAPI 3.0 (YAML) |
| API Communication | Axios + Automatically generated typed functions |
✅ Preparing the OpenAPI Schema
First, prepare the OpenAPI definition (swagger.json / yaml) on the backend.
paths:
/users:
get:
operationId: getUsers
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
components:
schemas:
User:
type: object
properties:
id:
type: string
name:
type: string
🔧 Type Generation: Automating TypeScript Code with openapi-ts
npx @hey-api/openapi-ts openapi.yml -o src/api/
With this command, typed code like the following is automatically generated:
export type User = {
id: string;
name: string;
};
export async function getUsers(): Promise<User[]> {
return axios.get('/users');
}
💡 How It Looks When Consuming the API
<script setup lang="ts">
import { getUsers } from '@/api';
const users = ref<User[]>([]);
onMounted(async () => {
users.value = await getUsers();
});
</script>
- Type completion works
- Guaranteed response types
- Early detection of endpoint names or parameter typos
⚠️ Common Pitfalls and Countermeasures
| Issue | Countermeasure |
|---|---|
| Code goes out of sync when schema updates | Auto-regenerate in CI every time or use watch mode |
| Want to unify Axios settings | Wrap a common axiosInstance and export it |
Want to handle server errorCode with types |
Use custom extensions like x-error-code and a mapping strategy |
🧪 Supplement: Leveraging Interceptors
- By utilizing interceptors in this way, you can omit
try-catchblocks for each API call while centralizing UI feedback for token expiration or communication errors.
client.interceptors.response.use(
res => res,
err => {
// Common error handling
return Promise.reject(err);
}
);
✅ Conclusion
With OpenAPI + TypeScript + Axios, API communication in Vue apps evolves in the following ways:
- 🚫 Eliminates type mismatches
- 🚀 Speeds up development (code auto-generation)
- 🛡️ Creates a type-safe and highly maintainable architecture
Moving forward, you can design an even more robust system by handling error responses (such as validation errors) using common types as well.
Discussion