openapi-typescript + openapi-fetch
SkillDev toolsType-safe OpenAPI consumption in TypeScript using openapi-typescript and openapi-fetch.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the openapi-typescript + openapi-fetch skill
What this skill tells your AI
The instructions your AI receives, as published by getopenpost/openpost in .agents/skills/openapi-typescript/SKILL.md and read by ahel’s review.
Type-safe OpenAPI consumption in TypeScript. Generates runtime-free types from OpenAPI specs and provides a typed fetch client.
Type Generation
# Generate types from local spec
npx openapi-typescript openapi.json -o src/lib/api/types.d.ts
# Generate from running server
npx openapi-typescript http://localhost:8080/openapi.json -o src/lib/api/types.d.ts
# Check if types are up-to-date (CI)
npx openapi-typescript openapi.json -o src/lib/api/types.d.ts --check
openapi-fetch Client
import createClient from "openapi-fetch";
import type { paths } from "./types";
const client = createClient<paths>({ baseUrl: "/api/v1" });
// GET with query params
const { data, error } = await client.GET("/posts", {
params: { query: { workspace_id: "123" } },
});
// POST with body
const { data, error } = await client.POST("/posts", {
body: { workspace_id: "123", content: "Hello", social_account_ids: [] },
});
// Path params
const { data } = await client.GET("/accounts/{platform}/auth-url", {
params: {
path: { platform: "x" },
query: { workspace_id: "123" },
},
});
Auth Middleware
import createClient, { type Middleware } from "openapi-fetch";
const client = createClient<paths>({ baseUrl: "/api/v1" });
client.use({
async onRequest({ request }) {
const token = localStorage.getItem("token");
if (token) {
request.headers.set("Authorization", `Bearer ${token}`);
}
return request;
},
});
Re-exporting Schema Types
// In client.ts
import type { paths, components } from "./types";
export type User = components["schemas"]["UserProfile"];
export type Workspace = components["schemas"]["WorkspaceResp"];
export type Post = components["schemas"]["PostResponse"];
Error Handling
Huma returns RFC 9457 Problem Details:
const { data, error } = await client.POST("/auth/login", {
body: { email, password },
});
if (error) {
// error is typed based on response schemas
console.error(error.detail); // human-readable message
console.error(error.status); // HTTP status code
console.error(error.errors); // validation details
}
Svelte Integration
<script lang="ts">
import { client, type Workspace } from '$lib/api/client';
let workspaces = $state<Workspace[]>([]);
async function load() {
const { data, error } = await client.GET('/workspaces');
if (!error && data) {
workspaces = data;
}
}
</script>
Workflow
- Backend defines types via Huma → auto-generates OpenAPI spec
- Frontend fetches spec from
/openapi.json openapi-typescriptgeneratestypes.d.tsopenapi-fetchprovides fully typed client- Both sides stay in sync — type mismatches caught at compile time
Scripts
{
"scripts": {
"generate:types": "openapi-typescript openapi.json -o src/lib/api/types.d.ts"
}
}
Gotchas
- Fields named
Statusin OpenAPI schemas get treated as HTTP status codes — avoid on response body structs $schemafield appears in generated types (Huma JSON Schema metadata) — ignore it in client code0001-01-01T00:00:00Zis Go's zero time — handle in frontend date formattingopenapi-typescriptrequires OpenAPI 3.0 or 3.1 (Huma generates 3.1)
Signals
- GitHub stars
- 138
- Forks
- 17
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
openapi-typescript- Source
- github.com/getopenpost/openpost