Type Generation¶
Litestar Vite includes a type generation system that keeps your frontend in sync with your Python backend.
Overview¶
The type generation pipeline:
Exports your Litestar OpenAPI schema to JSON
Generates TypeScript interfaces using
@hey-api/openapi-tsExtracts route metadata from your application
Generates a typed
route()helper for type-safe URL generation
Configuration¶
Enable type generation in your ViteConfig:
from litestar_vite.config import TypeGenConfig
VitePlugin(
config=ViteConfig(
types=TypeGenConfig(
output=Path("src/generated"), # default
generate_sdk=True, # generate API client
generate_routes=True, # generate routes.ts
)
)
)
Or use the shortcut for defaults:
VitePlugin(config=ViteConfig(types=True))
TypeGenConfig Reference¶
Parameter |
Default |
Description |
|---|---|---|
|
|
Output directory for all generated files |
|
|
Path for exported OpenAPI schema |
|
|
Path for routes metadata JSON |
|
|
Path for typed route helper (generated by Vite plugin) |
|
|
Generate Zod schemas for runtime validation |
|
|
Generate API client SDK via hey-api (fetch-based) |
|
|
Generate typed routes.ts file |
|
|
Generate Inertia page props types (effective only when Inertia is enabled) |
|
|
Path for page props metadata |
|
|
Fallback value type for untyped dict/list in page props ( |
|
|
Map schema/type names to TypeScript import paths for props types excluded from OpenAPI |
|
See below |
File patterns to watch for regeneration |
Default Inertia shared-props types (User, AuthData, FlashMessages) are controlled by
InertiaTypeGenConfig under InertiaConfig.type_gen.
Default watch patterns:
watch_patterns=["**/routes.py", "**/handlers.py", "**/controllers/**/*.py"]
hey-api Configuration¶
Litestar Vite uses hey-api/openapi-ts to generate TypeScript
types from your OpenAPI schema. Create an openapi-ts.config.ts in your project root:
import { defineConfig } from "@hey-api/openapi-ts"
export default defineConfig({
input: "./src/generated/openapi.json",
output: "./src/generated/api",
plugins: ["@hey-api/typescript", "@hey-api/schemas", "@hey-api/sdk", "@hey-api/client-axios"],
})
Available hey-api plugins:
@hey-api/typescript- Core TypeScript types (always included)@hey-api/schemas- JSON Schema exports@hey-api/sdk- Type-safe API client@hey-api/client-axios- Axios-based HTTP client@hey-api/client-fetch- Fetch-based HTTP client@hey-api/zod- Zod runtime validators
Generating Types¶
Generate all types with a single command:
litestar assets generate-types
This runs the full pipeline:
Exports OpenAPI schema to
src/generated/openapi.jsonRuns
npx openapi-tsto generate TypeScript typesGenerates
routes.tswith typed route helper
You can also export routes separately:
litestar assets export-routes
Generated Files¶
After running generate-types, your output directory contains:
src/generated/
├── openapi.json # OpenAPI schema from Litestar
├── routes.json # Route metadata
├── routes.ts # Typed route() helper
└── api/ # hey-api output (if generate_sdk=True)
├── index.ts # Barrel export
├── types.gen.ts # TypeScript interfaces
├── schemas.gen.ts # JSON schemas (if @hey-api/schemas)
└── sdk.gen.ts # API client (if @hey-api/sdk)
Using Generated Types¶
Import types and the route helper in your frontend:
import { route } from './generated/routes';
import type { Book, Summary } from './generated/api';
// Type-safe URL generation
const bookUrl = route('api:books.detail', { book_id: 123 });
// => "/api/books/123"
// Type-safe API calls
const response = await fetch(route('api:summary'));
const summary: Summary = await response.json();
Using the Generated SDK¶
If generate_sdk=True, hey-api generates a fully typed API client:
import { client, getApiSummary, getApiBooks } from './generated/api';
// Configure base URL (optional - defaults to same origin)
client.setConfig({ baseUrl: '/api' });
// Type-safe API calls with full IntelliSense
const { data: summary } = await getApiSummary();
const { data: books } = await getApiBooks();
// Parameters are typed
const { data: book } = await getApiBooksBookId({ path: { book_id: 1 } });
Typed Routes¶
The generated routes.ts provides Ziggy-style type-safe routing:
// If OpenAPI schemas include a `format`, `routes.ts` also emits semantic aliases
// and uses them in route parameter types (aliases are plain primitives, no runtime parsing).
export type UUID = string;
export type DateTime = string;
// Generated types
export type RouteName = "home" | "api:summary" | "api:books" | "api:books.detail";
export interface RoutePathParams {
"api:books.detail": { book_id: number };
"home": Record<string, never>;
// ... other routes
}
export interface RouteQueryParams {
"api:books.detail": Record<string, never>;
"home": Record<string, never>;
// ... other routes
}
type EmptyParams = Record<string, never>
type MergeParams<A, B> =
A extends EmptyParams ? (B extends EmptyParams ? EmptyParams : B) : B extends EmptyParams ? A : A & B
export type RouteParams<T extends RouteName> =
MergeParams<RoutePathParams[T], RouteQueryParams[T]>;
// Type-safe route function (params required only when needed)
export function route<T extends RoutesWithoutRequiredParams>(name: T): string;
export function route<T extends RoutesWithoutRequiredParams>(name: T, params?: RouteParams<T>): string;
export function route<T extends RoutesWithRequiredParams>(name: T, params: RouteParams<T>): string;
// Usage
route("home"); // "/"
route("api:books.detail", { book_id: 123 }); // "/api/books/123"
route("api:books.detail"); // TypeScript Error!
Note
For URL generation, route params never require null values. Optionality is represented by optional
query parameters (?:) and omission, matching how route() serializes values.
Auto-Regeneration¶
During development, types are regenerated when watched files change.
Configure patterns in TypeGenConfig:
TypeGenConfig(
watch_patterns=[
"**/routes.py",
"**/handlers.py",
"**/controllers/**/*.py",
"**/models/**/*.py", # Add custom patterns
],
)
Inertia Page Props¶
When using Inertia.js, enable page props generation:
VitePlugin(
config=ViteConfig(
types=TypeGenConfig(generate_page_props=True),
inertia=True,
)
)
This generates inertia-pages.json which the Vite plugin uses to create
page-props.ts with typed props for each page component.
See Type Generation for Inertia-specific details.
See Also¶
Type Generation - Inertia-specific type generation