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 createMockDataFn<T>() generator. The AI supplies the believable values, and the generator handles the rest. Like FriendlyText<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/core/formats';

// models/user.ts — the source type every enrichment example derives from.
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
rt$itemsarrays, tuplesthe element node (a MockData node for T[number])
rt$lengtharraysfixed length, or a [min, max] range
rt$optionalobjectspresent-probability (0 to 1) for optional members

Then feed it to the generator through the data option:

import {createMockDataFn} from '@ts-runtypes/core';
import type {User} from './user';
import {mockUser} from './mock-user';

const newUser = createMockDataFn<User>(undefined, {data: mockUser});

newUser();
// → { 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 createMockDataFn({ 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 mockUser: 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 createMockDataFn already lives) and normal tree-shaking keeps it out of your shipped code.
Copyright © 2026