===============
Type Generation
===============
Litestar Vite includes a type generation system that keeps your frontend in sync with your Python backend.
Overview
--------
The type generation pipeline:
1. Exports your Litestar OpenAPI schema to JSON
2. Generates TypeScript interfaces using ``@hey-api/openapi-ts``
3. Extracts route metadata from your application
4. Generates a typed ``route()`` helper for type-safe URL generation
Configuration
-------------
Enable type generation in your ``ViteConfig``:
.. code-block:: python
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:
.. code-block:: python
VitePlugin(config=ViteConfig(types=True))
TypeGenConfig Reference
-----------------------
.. list-table::
:widths: 25 15 60
:header-rows: 1
* - Parameter
- Default
- Description
* - ``output``
- ``src/generated``
- Output directory for all generated files
* - ``openapi_path``
- ``{output}/openapi.json``
- Path for exported OpenAPI schema
* - ``routes_path``
- ``{output}/routes.json``
- Path for routes metadata JSON
* - ``routes_ts_path``
- ``{output}/routes.ts``
- Path for typed route helper (generated by Vite plugin)
* - ``generate_zod``
- ``False``
- Generate Zod schemas for runtime validation
* - ``generate_sdk``
- ``True``
- Generate API client SDK via hey-api (fetch-based)
* - ``generate_routes``
- ``True``
- Generate typed routes.ts file
* - ``generate_page_props``
- ``True``
- Generate Inertia page props types (effective only when Inertia is enabled)
* - ``page_props_path``
- ``{output}/inertia-pages.json``
- Path for page props metadata
* - ``fallback_type``
- ``unknown``
- Fallback value type for untyped dict/list in page props (``unknown`` or ``any``)
* - ``type_import_paths``
- ``{}``
- Map schema/type names to TypeScript import paths for props types excluded from OpenAPI
* - ``watch_patterns``
- 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:
.. code-block:: python
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:
.. literalinclude:: /../examples/react/openapi-ts.config.ts
:language: typescript
:caption: openapi-ts.config.ts
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:
.. code-block:: bash
litestar assets generate-types
This runs the full pipeline:
1. Exports OpenAPI schema to ``src/generated/openapi.json``
2. Runs ``npx openapi-ts`` to generate TypeScript types
3. Generates ``routes.ts`` with typed route helper
You can also export routes separately:
.. code-block:: bash
litestar assets export-routes
Generated Files
---------------
After running ``generate-types``, your output directory contains:
.. code-block:: text
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:
.. code-block:: typescript
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:
.. code-block:: typescript
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:
.. code-block:: typescript
// 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;
// ... other routes
}
export interface RouteQueryParams {
"api:books.detail": Record;
"home": Record;
// ... other routes
}
type EmptyParams = Record
type MergeParams =
A extends EmptyParams ? (B extends EmptyParams ? EmptyParams : B) : B extends EmptyParams ? A : A & B
export type RouteParams =
MergeParams;
// Type-safe route function (params required only when needed)
export function route(name: T): string;
export function route(name: T, params?: RouteParams): string;
export function route(name: T, params: RouteParams): 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``:
.. code-block:: python
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:
.. code-block:: python
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 :doc:`/inertia/type-generation` for Inertia-specific details.
See Also
--------
- :doc:`/inertia/type-generation` - Inertia-specific type generation
- `hey-api Documentation `_
- `Example: react `_