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-catch blocks 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