Skip to content

Realistic data and types

The panel closes the loop around your data model in both directions: paste a model and get realistic data, or take a live response and get its types.

Paste a TypeScript interface — a dirty real-world one is fine: extends, Pick<...>, imports from libraries that are not present all resolve through the real TypeScript compiler, not a hand-rolled parser. laqi infers a shape from it and generates seeded values that look real, not "string" and 0:

interface User {
id: number
email: string
createdAt: string
priceCents: number
}
{ "id": 1, "email": "dell.roberts@example.net", "createdAt": "2026-08-24T09:12:00.000Z", "priceCents": 741.32 }

The same seed always produces the same output — pass seed to get byte-identical data across runs, useful for snapshot tests.

Every string and number/integer field is matched against a table of naming rules, in order — the first one whose pattern matches the field name wins. This is what makes email fields look like emails and createdAt look like a date, instead of both falling back to a random word.

String fields:

Field name patternProduces
ends in _at/At, or contains date/timea recent ISO date
contains emailan email address
exactly usernamea username
exactly filenamea filename with a .txt extension
name, firstName, lastName, fullName, displayNamea person’s full name
contains phonea phone number
contains avatar, image, photoan image URL
contains url, linka URL
contains citya city name
contains street, addressa street address
contains countrya country name
contains zip, postala zip code
contains uuid, guida UUID
contains description, bio, summarya sentence
contains titlethree lorem-ipsum words
anything elsetwo lorem-ipsum words

Number and integer fields:

Field name patternProduces
exactly id or _ida sequential integer — 1, 2, 3, … per field, per call
ends in _id or Id (e.g. userId, order_id)a foreign key, 1-1000
contains price, total, amount, costa decimal price
contains agean integer 18-80
contains count, quantity, qtyan integer 0-100
anything elsea random number in range, integer or decimal

Field-name matching is word-aware, not a raw substring test — candidate does not match date (the letters are buried mid-word), and userName matches the person-name rule before the generic fallback because name is a whole word inside it.

Every other JSON type generates directly from its shape: boolean, null, arrays (each item generated independently), objects (each field generated independently), and tuples (exact length, exact type per position — unlike the JSON Schema bridge used for type printing below, data generation never loses positional precision).

Every endpoint’s response has a Copy types button in the panel, with a language picker. Types are derived from the live response body on demand, so they can never go stale against a body you changed by hand.

The same operation works from an existing endpoint or from a pasted model, and covers 25 languages:

C (cJSON), C++, C#, Crystal, Dart, Elixir, Elm, Flow, Go, Haskell, Java, JavaScript, JavaScript PropTypes, JSON Schema, Kotlin, Objective-C, PHP, Pike, Python, Ruby, Rust, Scala 3, Smithy, Swift, TypeScript — plus TypeScript with Zod or Effect Schema validators built in.

// TypeScript
interface User {
id: number
email: string
}
// Go
type User struct {
ID int64 `json:"id"`
Email string `json:"email"`
}

Nothing about this is persisted beyond ordinary mock JSON — a pasted model is never saved, and generated data lands in your laqi/ files through the same write path the panel’s endpoint editor uses.

Both directions are MCP tools — generate_data and get_types — so an agent can paste a model from a backend discussion, generate a realistic body, and hand back typed code in one pass. See Using laqi with AI agents.