Control runtime validation depth, input/output boundaries, and generated domain types.
These options apply when --runtime is not none.
Think of these controls as a boundary policy: depth decides how strict a schema is, side decides where it runs, and transforms decide the values application code receives.
Choose validation depth
Section titled “Choose validation depth”| Level | Checks |
|---|---|
loose | object, array, primitive, enum, and union structure |
formats | loose checks plus known formats such as email, UUID, URL, IP, and date/time |
strict | formats plus string, number, array, and object constraints |
pnpm exec typed-openapi openapi.yaml --runtime zod --validation formatsstrict is the default for a runtime adapter. Use loose for a structurally reliable but less opinionated boundary.
Tune a preset
Section titled “Tune a preset”Every preset resolves to the following policy. A policy object can override any field without losing the rest of its preset:
| Field | loose | formats | strict |
|---|---|---|---|
formats | off | on | on |
stringConstraints | off | off | on |
numberConstraints | off | off | on |
arrayConstraints | off | off | on |
objectConstraints | off | off | on |
import { defineConfig } from "typed-openapi";
export default defineConfig({ runtime: "zod", validation: { preset: "strict", stringConstraints: false, numberConstraints: false, },});Use this for a deliberate compatibility exception. Prefer a named preset when it already matches the API boundary you want.
Validate only the side you need
Section titled “Validate only the side you need”Generated clients validate both outgoing parameters and successful response data by default.
# Validate untrusted server responses, but skip outgoing checks.pnpm exec typed-openapi openapi.yaml --runtime valibot --validate-side output| Value | Behavior |
|---|---|
none | generate schemas but do not call them |
input | validate path, query, cookie, header, and body parameters |
output | validate successful response data |
both | validate input and output (default) |
You can override the generated default for one request:
await api.post("/pet", { body: draft, validate: "input",});For trusted internal calls, validate: "none" can be a useful escape hatch. Keep that exception local and documented; a global validateSide: "none" removes the runtime boundary for every endpoint.
Plug in your own validator call
Section titled “Plug in your own validator call”The emitted runtime schema is passed to an optional onValidate hook. This is useful when an application wraps validation with telemetry, localization, or a custom error type.
import { z } from "zod";
api.setOnValidate(async ({ side, schema, value }) => { console.info(`validating ${side}`); return (schema as z.ZodType).parse(value);});Coerce HTTP primitives
Section titled “Coerce HTTP primitives”Path, query, cookie, and header values arrive as strings in HTTP. --coerce makes runtime schemas accept string versions of number and boolean values. It is enabled by default when a runtime is selected.
pnpm exec typed-openapi openapi.yaml --runtime zod --coerce# Keep strict input typing and disable coercion when the transport already normalizes values:pnpm exec typed-openapi openapi.yaml --runtime zod --no-coerceTransform date and bigint fields
Section titled “Transform date and bigint fields”Map OpenAPI formats into application-friendly values across TypeScript types and runtime schemas:
pnpm exec typed-openapi openapi.yaml \ --runtime zod \ --transform-dates \ --transform-bigintformat: dateanddate-timebecomeDate.format: int64becomesbigint.- With the types-only runtime, ISO date strings are revived for the generated client path.
Defaults and read/write fields
Section titled “Defaults and read/write fields”OpenAPI default values are emitted in runtime schemas. For inline request objects, readOnly properties are removed from input schemas; for inline response objects, writeOnly properties are removed from output schemas. Named $ref components remain shared so a component’s public shape does not silently differ between endpoints.
For browser apps, start with strict, both, and coercion enabled. If forms or the transport already validate outgoing values, move to output validation rather than disabling runtime checks entirely.