Type generation
Type generation
AppKit can automatically generate TypeScript types for your SQL queries, providing end-to-end type safety from database to UI.
Goal
Generate type-safe TypeScript declarations for query keys, parameters, and result rows.
All generated files live in shared/appkit-types/, one per plugin (e.g. analytics.d.ts). They use declare module to augment existing interfaces, so the types apply globally — you never need to import them. TypeScript auto-discovers them through "include": ["shared/appkit-types"] in your tsconfig.
Vite plugin: appKitTypesPlugin
The recommended approach is to use the Vite plugin, which watches your SQL files and regenerates types automatically during development.
Configuration
outFile?: string- Output file path (default:shared/appkit-types/analytics.d.ts)watchFolders?: string[]- Folders to watch for SQL files (default:["../config/queries"])
Example
// client/vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { appKitTypesPlugin } from "@databricks/appkit";
export default defineConfig({
plugins: [
react(),
appKitTypesPlugin({
watchFolders: ["../config/queries"],
}),
],
});
Important nuance
When the frontend is served through AppKit in dev mode, AppKit's dev server already includes appKitTypesPlugin() internally. You still want it in your client build pipeline if you run vite build separately.
CLI: npx @databricks/appkit generate-types
For manual type generation or CI/CD pipelines, use the CLI command:
# Requires DATABRICKS_WAREHOUSE_ID (or pass as 3rd arg)
npx @databricks/appkit generate-types [rootDir] [outFile] [warehouseId]
Examples
-
Generate types using warehouse ID from environment
npx @databricks/appkit generate-types . shared/appkit-types/analytics.d.ts -
Generate types using warehouse ID explicitly
npx @databricks/appkit generate-types . shared/appkit-types/analytics.d.ts abc123... -
Force regeneration (skip cache)
npx @databricks/appkit generate-types --no-cache
Warehouse readiness and the --wait flag
By default, generate-types is non-blocking: it never waits on — or fails because of — your SQL warehouse. It writes the best types it can immediately (reusing cached types where the query is unchanged, otherwise result: unknown) and then spawns a detached background worker that refreshes the real types once the warehouse is ready. This keeps npm install (postinstall) and npm run dev (predev) fast and resilient to a cold or briefly-unreachable warehouse. The dev Vite plugin behaves the same way: types appear instantly and refresh in place once the warehouse is live.
Pass --wait for CI and production builds, where accurate types must be present before the build proceeds:
npx @databricks/appkit generate-types --wait
In blocking mode the generator starts a stopped warehouse, waits (bounded) for it to reach RUNNING, and then describes your queries. It fails only when the configured warehouse no longer exists (deleted/deleting), so a transient outage or a cold warehouse degrades gracefully rather than breaking the build. The app template wires this up for you: postinstall and predev run the non-blocking default, while prebuild runs --wait.
How it works
The type generator:
- Scans your
config/queries/folder for.sqlfiles - Parses SQL parameter annotations (e.g.,
-- @param startDate DATE) - Connects to your Databricks SQL Warehouse to infer result column types
- Generates TypeScript interfaces for query parameters and results
- Creates a
QueryRegistrytype for type-safe query execution
Parameters during DESCRIBE QUERY
Type generation describes each query without binding real parameters, so it
substitutes a placeholder default for every :param (e.g. '' for a string).
That breaks queries whose shape depends on a value — most notably dynamic table
names via IDENTIFIER(:catalog || '.schema.table'). Annotate such parameters
with a sample value (-- @param catalog STRING = main) so the describe call can
resolve a real table. The sample value is used only at type-generation time; the
runtime query still binds the actual parameter. See
SQL parameters → Sample values.
Using generated types
Once types are generated, your IDE will provide autocomplete and type checking:
import { useAnalyticsQuery } from "@databricks/appkit-ui/react";
import { sql } from "@databricks/appkit-ui/js";
// TypeScript knows "users_list" is a valid query key
// and what parameters it expects
const { data } = useAnalyticsQuery("users_list", {
status: sql.string("active"),
limit: sql.number(50),
});
// TypeScript knows the shape of the result rows
data?.forEach(row => {
console.log(row.email); // ✓ autocomplete works
});
See also
- Plugins - Analytics plugin configuration
- API Reference - Complete UI components API documentation