TypeScript
Kubb is built in TypeScript end-to-end. Every public surface accepts a generic that pins down options, resolved options, and the resolver shape. This includes defineConfig, definePlugin, defineMiddleware, defineParser, createAdapter, defineGenerator, and the AST factories. The result is a config file where IntelliSense leads you through every choice and the compiler catches mistakes before generation runs.
Quick start
Use the kubb.config.ts entry point and the compiler will infer everything from there:
import { } from 'kubb'
import { } from '@kubb/plugin-ts'
export default ({
: { : './petStore.yaml' },
: { : './src/gen', : true },
: [
({
: { : 'models' },
// Hover any option to see the inferred type.
}),
],
})Strict mode
Kubb assumes TypeScript strict mode. All exported types are written to compile cleanly under "strict": true, and several APIs (notably the AST node guards and resolvers) only narrow correctly when strictNullChecks is on:
{
"compilerOptions": {
"strict": true,
"moduleResolution": "bundler",
"module": "ESNext",
"target": "ES2022"
}
}IMPORTANT
If you cannot enable full strict, enable at least strictNullChecks. Without it, RefSchemaNode.ref and resolver helpers return widened types and you'll have to cast manually.
Typing plugin options
Plugins use a single generic, PluginFactoryOptions, that carries four pieces of information through the entire plugin lifecycle:
| Generic | Purpose |
|---|---|
TName | The plugin's name literal (e.g. 'plugin-ts'). Used by dependencies lookups. |
TOptions | The user-facing options accepted by the factory. |
TResolvedOptions | The shape of options after defaults have been applied (what runs at runtime). |
TResolver | The plugin's Resolver extension (pluginName, naming helpers). |
Declare a PluginFactoryOptions alias once and reuse it:
import { } from '@kubb/core'
import type { , } from '@kubb/core'
type = { ?: string }
type = <>
type = <'plugin-example', , , >
export const = <>(() => {
const : = { : . ?? '.ts' }
return {
: 'plugin-example',
: ,
: {
'kubb:plugin:end'({ }) {
// `files` is FileNode[]; no cast required.
.(`${.} files emitted with suffix ${.}`)
},
},
}
})TIP
Inside hooks, ctx.options is typed as TResolvedOptions and ctx.config is the fully-resolved Config. No casts required.
Typing adapter options
Adapters follow the same pattern with AdapterFactoryOptions. Pin TName, TOptions, TResolvedOptions, and the parsed TDocument once:
import { } from '@kubb/core'
import { } from '@kubb/ast'
import type { } from '@kubb/core'
type = { ?: boolean }
type = <>
type = { : <string, unknown> }
type = <'adapter-example', , , >
export const = <>(() => ({
: 'adapter-example',
: { : . ?? false },
: null,
async () {
return ()
},
() {
return []
},
async () {
// Throw or call ctx.error here when the spec is invalid.
},
}))The same alias flows into Adapter<AdapterExample>, so consumers that import the adapter type get full type information about its options and document.
Typing middlewares and parsers
Middlewares accept their own options generic on defineMiddleware:
import { } from '@kubb/core'
type = { ?: string }
export const = <>(() => ({
: 'middleware-stats',
: {
'kubb:plugins:end'({ }) {
.(`${. ?? 'kubb'}: ${.} files`)
},
},
}))Parsers receive a FileNode<TMeta> in parse, so typing the parameter keeps plugin-attached metadata typed:
import { } from '@kubb/core'
import type { } from '@kubb/ast'
type = { : 'ts' | 'tsx' }
export const = ({
: 'parser-typed',
: ['.ts'],
(: <>) {
const = . // typed as Meta
return `// ${?. ?? 'unknown'}\n`
},
() {
return ''
},
})Narrowing AST nodes
The SchemaNode union shares one kind: 'Schema' discriminator and uses node.type to differentiate variants. Use the type guards from @kubb/ast to narrow without casts:
import { , } from '@kubb/ast'
import type { } from '@kubb/ast'
declare const :
const = (, 'ref')
if (?.) {
const : string = .
.()
}
const : unknown =
if (()) {
// child is now SchemaNode
const : 'Schema' = .
}Available guards on @kubb/ast: isInputNode, isOutputNode, isOperationNode, isHttpOperationNode, isSchemaNode. For schema variants use narrowSchema(node, type); for HTTP operations use isHttpOperationNode(node) to narrow to an HttpOperationNode with non-nullable method/path.
See also
- Plugins:
definePlugin,PluginFactoryOptions, resolvers, generators. - Adapters:
createAdapterandAdapterFactoryOptions. - AST: node types, visitors, guards.
- Configuration: top-level
defineConfigshape.