AI Integration

MockData

Realistic sample data for a type, checked against its fields at build time.

MockData<T> gives a type realistic sample values: pools of believable names and emails, ranges for numbers and dates, and a few hints for arrays and optional fields. It feeds the createMockType<T>() generator. The AI supplies the believable values, and the generator handles the rest. Like FriendlyType<T>, you commit it next to your type and the compiler checks it against that type on every build.

How it's shaped

The map mirrors your type. Each field carries the knobs that make sense for its kind. The compiler scaffolds an entry for every field with the blanks marked @todo, then the agent fills in believable values.

import type * as TF from 'ts-runtypes/formats';

// models/user.ts
export interface User {
  name: TF.String<{ minLength: 2; maxLength: 60 }>;
  age: TF.Number<{ min: 0; max: 120 }>;
  isActive: boolean;
  tags: string[];
  profile: {
    email: TF.Email;
    score: TF.Number<{ min: 0; max: 100 }>;
  };
}

The per-field knobs, by kind:

KnobApplies toWhat it does
poolstrings, numbers, booleans, bigints, …draw the value from this list
min / maxnumbers, datesbound the generated range
$itemsarrays, tuplesthe element node (a MockData node for T[number])
$lengtharraysfixed length, or a [min, max] range
$optionalobjectspresent-probability (0 to 1) for optional members

Then feed it to the generator through the data option:

import { createMockType } from 'ts-runtypes';
import { userMock } from 'runtypes/generated/models/user';

const mockUser = createMockType<User>({ data: userMock });

mockUser();
// → { name: 'Liang Wei', age: 41, isActive: true,
//     tags: ['beta', 'vip'],
//     profile: { email: 'liang@corp.io', score: 73 } }
The data option is purely additive. Leave it out and the generator works exactly as it does today. The MockData<T> type and the createMockType({ data }) integration ship today; the build-time check on pool values is still in development.

Every sample value is checked

Because RunTypes already knows how to validate, the compiler checks that every value in your pools and ranges is actually valid for its field, at build time and not when your tests run. If an AI drops a malformed address into the email pool, or a score of 150, the build catches it:

export const userMock: MockData<User> = {
  profile: {
    email: { pool: ['alice@example.com', 'not-an-email'] },   // error: 'not-an-email' isn't a valid email
    score: { min: 0, max: 150 },                              // error: 150 is above the field's max of 100
  },
};

No other mock library does this; it falls straight out of the validator RunTypes already has. (Mistakes like min above max get flagged too.)

Format-aware by default

Even without a pool, the generator already respects type formats: an email field gets a real-looking address, a uuidv4 field a real-looking UUID. MockData<T> is for when mechanical-but-valid isn't enough and you want believable: real names in name, your own domains in email, realistic ranges in age. Anything you don't pin falls back to the format-aware mechanical generator.

Mock pools get big and almost never belong in a production bundle. Use MockData<T> in tests and seed scripts (the same place createMockType already lives) and normal tree-shaking keeps it out of your shipped code.
Copyright © 2026