Home
DT

Convert SQL DDL to TypeScript interfaces

Paste a CREATE TABLE statement and get interfaces, JSON Schema, Pydantic or Zod.

This tool runs entirely in your browser. Nothing you type is sent to a server.

The moment your database schema and your application types drift apart, bugs start quietly. A column declared VARCHAR(255) NULL that your code types as string will throw the day a real null arrives. This converter reads a CREATE TABLE statement — column types, nullability, ENUM values, inline comments — and turns it into TypeScript interfaces, Zod schemas, Pydantic models or JSON Schema.

It handles the DDL dialects you actually encounter: MySQL backticks, PostgreSQL double quotes, SQL Server brackets, schema-qualified table names, multi-word types like DOUBLE PRECISION and TIMESTAMP WITH TIME ZONE, PostgreSQL array columns (TEXT[]), and table-level PRIMARY KEY (id) constraints. Everything runs in your browser, so pasting a production schema never sends it anywhere.

How to use

  1. Paste your DDLDrop one or more CREATE TABLE statements into the left pane. Line comments, block comments and index definitions like UNIQUE KEY are filtered out automatically. The detected tables and their column counts appear below the input.
  2. Pick an output formatChoose TypeScript interfaces, Zod (runtime validation), Pydantic (FastAPI and Python backends), JSON Schema (OpenAPI docs) or a JSON sample (mock data and API examples). Switching formats keeps your input intact.
  3. Tune naming and nullabilityTurn on camelCase to convert snake_case columns to front-end conventions. Decide whether nullable columns become field?: string or field: string | null with the optional-marker toggle — the former suits form payloads, the latter matches what an API actually returns.
  4. Copy or downloadUse the copy button for the clipboard or download a .ts, .py or .json file named after the first table in your schema.

Frequently asked questions

Does it understand both MySQL and PostgreSQL DDL?

Yes. Backtick-quoted MySQL identifiers, double-quoted PostgreSQL identifiers and bracketed SQL Server identifiers are all parsed.

Type mapping is dialect-aware too. MySQL's TINYINT(1) is conventionally a boolean, so it maps to boolean, and ENUM('a','b') becomes the literal union "a" | "b". PostgreSQL's SERIAL and BIGSERIAL are treated as NOT NULL because they auto-populate, TEXT[] becomes string[], and JSONB becomes Record<string, unknown>.

My DATE columns become Date, but I want strings.

TypeScript output maps temporal columns to Date because that is what ORMs such as Prisma and TypeORM hand back.

If you are typing a JSON API response instead, string is correct. Use the JSON Schema output, which emits { "type": "string", "format": "date-time" }, or the Zod output, whose z.coerce.date() accepts an ISO string and converts it — safe to use directly against JSON payloads.

Is my schema uploaded anywhere?

No. Parsing and code generation happen entirely in the JavaScript running on this page.

The site is deployed as static files with no backend that could receive input. Open your browser's network tab while converting and you will see that no request is made. Pasting an internal production schema is safe.

Can I use the generated types in production as-is?

They are a solid starting point, but read them once before committing.

DECIMAL and NUMERIC columns map to number in TypeScript, and JavaScript's double-precision floats lose accuracy on monetary values. For those columns, receiving a string and computing with a decimal library is safer. The Pydantic output already maps them to Decimal.

Concepts worth knowing

Where SQL types and language types diverge

SQL encodes length in the type (VARCHAR(80)); TypeScript's string has no length. Conversely, a TypeScript union can only be approximated in SQL by an ENUM.

Because of that gap, generated types are compile-time hints, not runtime guarantees. If you need real validation, use the Zod output and call schema.parse(data) at your API boundary — length constraints (z.string().max(80)) and integer checks (z.number().int()) come along for free.

NULL, undefined and optional are three different things

SQL's NULL means 'no value'. TypeScript has two candidates for that idea, and they behave differently. field?: string means the key may be absent; field: string | null means the key is present with a null value.

Serialization makes the difference concrete: JSON.stringify drops undefined properties entirely but preserves null. For a row returned straight from the database, | null matches reality. For the body of a PATCH request, ? is the better fit.

Treating the schema as the single source of truth

Hand-maintained types drift as migrations accumulate. The healthier pattern is to treat the database schema as the source of truth and derive types from it.

At scale, wire up Prisma, Drizzle, sqlc or SQLAlchemy in CI so generation is automatic. But before that pipeline exists — or when another team hands you nothing but a DDL file, or you need to bolt on one legacy table today — pasting and getting an answer in two seconds is simply faster.

Related tools

Last updated: 2026-08-12