Guides

Exporting Your OpenAPI Spec

openapi-typescript can generate types directly from a running server — no need to export to a file first. There are two approaches:

If your Go API is running and serves the OpenAPI spec at an endpoint (e.g. /docs/json), you can point openapi-typescript directly at it:

package.json
{
  "scripts": {
    "generate:api-schema": "npx openapi-typescript http://localhost:3434/docs/json -o ./app/types/api-schema.ts"
  }
}
package.json
{
  "scripts": {
    "generate:api-schema": "bunx openapi-typescript http://localhost:3434/docs/json -o ./app/types/api-schema.ts"
  }
}

Start your Go server, then run:

npm run generate:api-schema
bun run generate:api-schema

This fetches the live spec and generates types in one step. Adjust the URL and port to match your server configuration.

Option 2: Export to a file first

If you prefer to work with a local file (useful for CI/CD or offline generation), export the spec from your Go app:

cmd/generate-spec/main.go
package main
 
import (
    "encoding/json"
    "os"
 
    openswag "github.com/andrianprasetya/open-swag-go"
)
 
func main() {
    docs := openswag.New(openswag.Config{
        Title:   "My API",
        Version: "1.0.0",
    })
 
    // Register your endpoints
    registerEndpoints(docs)
 
    spec, err := docs.GenerateSpec()
    if err != nil {
        panic(err)
    }
 
    data, _ := json.MarshalIndent(spec, "", "  ")
    os.WriteFile("openapi.json", data, 0644)
}
go run cmd/generate-spec/main.go

Or curl it from a running server:

curl http://localhost:3434/docs/json -o openapi.json

Then generate types from the file:

package.json
{
  "scripts": {
    "generate:api-schema": "npx openapi-typescript ./openapi.json -o ./app/types/api-schema.ts"
  }
}
package.json
{
  "scripts": {
    "generate:api-schema": "bunx openapi-typescript ./openapi.json -o ./app/types/api-schema.ts"
  }
}

openapi-typescript

openapi-typescript generates TypeScript types directly from an OpenAPI spec. It produces type definitions only — no runtime code.

Setup

npm install -D openapi-typescript
bun add -d openapi-typescript

Then add a generate:api-schema script as shown in Exporting Your OpenAPI Spec above and run it.

Usage

src/api/client.ts
import type { paths } from './types';
 
type ListUsersResponse = paths['/api/users']['get']['responses']['200']['content']['application/json'];
type CreateUserBody = paths['/api/users']['post']['requestBody']['content']['application/json'];

openapi-fetch

openapi-fetch builds on openapi-typescript to provide a type-safe fetch client with zero runtime overhead.

Setup

npm install openapi-fetch
npm install -D openapi-typescript
bun add openapi-fetch
bun add -d openapi-typescript

Generate types first, then create a client:

src/api/client.ts
import createClient from 'openapi-fetch';
import type { paths } from './types';
 
const client = createClient<paths>({
  baseUrl: 'https://api.example.com',
});
 
// Fully typed — params, body, and response are all inferred
const { data, error } = await client.GET('/api/users', {
  params: {
    query: { page: 1, limit: 20 },
  },
});
 
// data is typed as ListUsersResponse
// error is typed as the error response

Usage with React

src/hooks/useUsers.ts
import { useEffect, useState } from 'react';
import { client } from '../api/client';
 
export function useUsers(page: number) {
  const [users, setUsers] = useState<Awaited<ReturnType<typeof fetchUsers>>>();
 
  async function fetchUsers() {
    const { data } = await client.GET('/api/users', {
      params: { query: { page } },
    });
    return data;
  }
 
  useEffect(() => {
    fetchUsers().then(setUsers);
  }, [page]);
 
  return users;
}

Usage with Next.js Server Components

app/users/page.tsx
import { client } from '@/api/client';
 
export default async function UsersPage() {
  const { data } = await client.GET('/api/users', {
    params: { query: { page: 1 } },
  });
 
  return (
    <ul>
      {data?.users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

Orval

Orval generates a complete API client with React Query hooks, Axios instances, or custom HTTP clients.

Setup

npm install -D orval
bun add -d orval

Create a configuration file:

orval.config.ts
import { defineConfig } from 'orval';
 
export default defineConfig({
  api: {
    input: './openapi.json',
    output: {
      target: './src/api/generated.ts',
      client: 'react-query',
      mode: 'tags-split',
    },
  },
});

Add a script:

package.json
{
  "scripts": {
    "generate:api": "npx orval"
  }
}
package.json
{
  "scripts": {
    "generate:api": "bunx orval"
  }
}

Usage with React Query

src/components/UserList.tsx
import { useListUsers } from '../api/generated/users';
 
export function UserList() {
  const { data, isLoading } = useListUsers({ page: 1, limit: 20 });
 
  if (isLoading) return <div>Loading...</div>;
 
  return (
    <ul>
      {data?.users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}

Usage with Vue

orval.config.ts
import { defineConfig } from 'orval';
 
export default defineConfig({
  api: {
    input: './openapi.json',
    output: {
      target: './src/api/generated.ts',
      client: 'vue-query',
    },
  },
});
src/components/UserList.vue
<script setup lang="ts">
import { useListUsers } from '../api/generated/users';
 
const { data, isLoading } = useListUsers({ page: 1, limit: 20 });
</script>
 
<template>
  <div v-if="isLoading">Loading...</div>
  <ul v-else>
    <li v-for="user in data?.users" :key="user.id">{{ user.name }}</li>
  </ul>
</template>

Comparison

Featureopenapi-typescriptopenapi-fetchOrval
Types only
Fetch client
React Query hooks
Vue Query hooks
Runtime overheadNoneMinimalVaries
Custom HTTP clientN/AFetchAxios, Fetch, Angular