Javascript is required
Best practicesPublished 2026-07-285 min read

OpenAPI to TypeScript: Generation and Validation

An OpenAPI schema describes an API contract, while generated TypeScript projects that contract into compile-time code. Generation can align request and response fields, but it does not validate runtime JSON and cannot replace required, nullable, additionalProperties, or response semantics in the document.

By: Tiny
OpenAPISwaggerJSON to TypeScriptCode GenerationRuntime Validation

1. Problem: generated types do not validate responses

OpenAPI required controls property presence, while nullable in 3.0 or a type union in 3.1 controls null. A generator may emit an optional property or a union. TypeScript checks code that has entered the type system; a network response is still unknown.

2. Minimal reproduction: schema and generated type are different layers

This schema uses the OpenAPI 3.0 nullable form; OpenAPI 3.1 commonly uses a JSON Schema type union. Actual output depends on document version and generator settings.

const userSchema = {
  type: "object",
  required: ["id"],
  properties: {
    id: { type: "string" },
    displayName: { type: "string", nullable: true },
  },
};
// A generator may produce:
type User = { id: string; displayName?: string | null };
console.log(userSchema.required); // ["id"]

3. Root cause: OpenAPI version, generator, and runtime have separate jobs

OpenAPI 3.0 and 3.1 express nullable differently, and format is commonly a semantic hint rather than a JavaScript runtime check. A generator reads schemas, TypeScript enforces compile-time assumptions, and a runtime validator checks unknown JSON. None replaces the others.

4. Recommendation: keep the OpenAPI schema as the contract source

Validate the OpenAPI document first, then generate TypeScript with a fixed version and configuration. Distinguish requestBody, parameters, responses, required, readOnly, writeOnly, and additionalProperties. Validate runtime responses with a validator tied to the schema and retain paths plus source context on failure.

5. Complete code: add a runtime guard beside the generated type

This example shows a schema-aligned TypeScript type and a hand-written runtime guard. It is not an invented generator or validator API; it demonstrates why static and runtime layers are both needed.

type User = {
  id: string;
  displayName?: string | null;
};
function isUser(value: unknown): value is User {
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
  const record = value as Record<string, unknown>;
  if (typeof record.id !== "string") return false;
  return record.displayName === undefined || record.displayName === null || typeof record.displayName === "string";
}
const payload: unknown = { id: "u-1", displayName: null };
if (!isUser(payload)) throw new Error("Response does not match User schema");
console.log(payload.id); // u-1

6. Incorrect approaches

Inferring TypeScript from one response and calling it an OpenAPI contract misses required fields, nullability, and alternate responses. Trusting fetch data because an interface was generated skips runtime checks. Treating format: date-time as a Date instance also exceeds what the schema usually guarantees.

7. Boundaries: nullable, extra properties, and request/response

Interpret OpenAPI 3.0 nullable and OpenAPI 3.1 JSON Schema unions according to the document version. additionalProperties, readOnly, and writeOnly affect request and response models. A referenced or composed schema can produce different effective fields per operation; one flattened interface may hide that.

8. Verification

Validate the OpenAPI document, generate TypeScript, and run tsc. Prepare missing required fields, null, extra properties, wrong types, and valid request/response samples for a runtime validator. Record OpenAPI version, generator version, and configuration when reviewing generated diffs.

9. FAQ

Are Swagger and OpenAPI unrelated contracts? Swagger is a historical name and tool ecosystem around OpenAPI; confirm the document version and schema syntax.

Do generated TypeScript types remove runtime validation? No; network data remains unknown at runtime.

Does format: uuid create a UUID class? Usually it is a format hint; generation and runtime behavior depend on tools and configuration.

10. Summary

OpenAPI is the contract source, code generation projects it into compile-time TypeScript, and runtime validation checks actual JSON. Handle nullable, required, composition, and extra properties by OpenAPI version, validate requests and responses separately, and record generator configuration.

Sources and further reading

Specifications and references for checking the article’s technical details.

Related articles

Keep exploring

Use the related browser tool to test the workflow with your own sample data.

Open related tool