Beta You're reading the docs for Kubb v5, which is currently in beta. View the stable v4 docs
Skip to content

TypeScript

Kubb is built in TypeScript end to end. Every public surface takes a generic that pins down options, resolved options, and the resolver shape: defineConfig, definePlugin, defineParser, createAdapter, defineGenerator, and the AST factories. 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 infers everything from there:

kubb.config.ts
typescript
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 compile cleanly under "strict": true, and several APIs (notably the AST node guards and resolvers) narrow correctly only when strictNullChecks is on:

tsconfig.json
json
{
  "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 cast manually.

Typing plugin options

Plugins use a single generic, PluginFactoryOptions, that carries four pieces of information through the 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 are applied (what runs at runtime).
TResolver The plugin's Resolver extension (pluginName, naming helpers).

Declare a PluginFactoryOptions alias once and reuse it:

plugin-example.ts
typescript
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:

adapter-example.ts
typescript
import { ,  } from '@kubb/core'
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 parsers

Parsers receive a FileNode<TMeta> in parse, so typing the parameter keeps plugin-attached metadata typed:

parser-typed.ts
typescript
import { ,  } from '@kubb/core'

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 tell variants apart. Use narrowSchema to narrow a SchemaNode to a specific variant, and isHttpOperationNode to narrow an OperationNode to an HttpOperationNode:

narrow.ts
typescript
import {  } from '@kubb/core'

declare const : .

const  = .(, 'ref')
if (?.) {
  const : string = .
  .()
}

declare const : .
if (.()) {
  // op is now HttpOperationNode. method and path are non-nullable
  const : . = .
}

These are the only two guards @kubb/ast exports. Everything else narrows through the kind and type discriminants directly.

See also

  • Plugins: definePlugin, PluginFactoryOptions, resolvers, generators.
  • Adapters: createAdapter and AdapterFactoryOptions.
  • AST: node types, visitors, guards.
  • Configuration: top-level defineConfig shape.