Guide

Data Mocking

Generate valid or invalid type-shaped fake data for tests and fixtures.

Make some fake data

// createMockDataFn -> a function that invents a fresh, valid User every call.
const mockUser = createMockDataFn<User>();

const a = mockUser(); // {id: 91, name: 'qZ...', roles: ['user'], active: true}
const b = mockUser(); // a different one each time

// Whatever it produces passes the validator for the same type — by construction.
const isUser = createValidateFn<User>();
isUser(mockUser()); // true

Call the generator as many times as you like. You get fresh, valid data every time. Change the type and the mocks follow along, with no fixture to update.

createMockDataFn needs the Vite plugin running to read your type. It throws a clear error if the plugin isn't active. It's a build-time tool, so reach for it in tests and seed scripts, not shipped runtime code.

Steer it with options

Pass a mock options bag to shape the generated values: number ranges, string lengths, how often optionals show up, and more. The same options are accepted on the factory (where they apply to every call) and per call, and they merge in order: built-in defaults first, then factory options, then per-call options.

// Options can be set at the factory (apply to every call) or per call.
// They merge: defaults < factory < call.
const mockAccount = createMockDataFn<Account>(undefined, {
  mock: {
    minNumber: 0,
    maxNumber: 1000, // numbers land in [0, 1000]
    stringLength: 8, // every generated string is 8 chars
    optionalProbability: 1, // always include optional props like `tags`
  },
});

const rich = mockAccount({mock: {minNumber: 1_000_000}}); // override just for this call

The full set, grouped by what they control.

Value ranges and lengths

OptionWhat it does
minNumber / maxNumberInclusive bounds for generated numbers and bigints.
stringLength / maxRandomStringLengthForce, or cap, generated string length.
stringCharSetThe character set strings are built from.
arrayLength / maxRandomItemsLengthForce, or cap, array, Map, Set and record sizes.
minDate / maxDateInclusive bounds for generated dates (a timestamp or a Date).

Pools and pins

OptionWhat it does
anyValuesListThe pool the any and unknown kinds draw from.
objectListThe pool the plain object kind draws from.
regexpListThe pool the RegExp kind draws from.
symbolName / symbolLength / symbolCharSetFix a generated symbol's name, or its random length and character set.
unionIndex / enumIndexPin a union member or enum branch instead of picking at random.

Optionality and recursion

OptionWhat it does
optionalProbabilityChance from 0 to 1 that an optional property is included.
optionalPropertyProbabilityPer-property override of that chance, keyed by property name.
maxMockRecursionHow far a recursive type is followed before it bottoms out.

Promises

OptionWhat it does
promiseTimeOutDelay in milliseconds before a mocked Promise resolves (0 resolves immediately).
promiseRejectWhen set, the mocked Promise rejects with this value instead of resolving.

Advanced

OptionWhat it does
nonDataTypesAlso generate the non-data members (functions, methods, symbols, non-serializable natives) a mock normally leaves out. Off by default.
tupleOptions / paramsOptionsPer-slot options for a tuple's elements. paramsOptions is an alias that also covers a function's Parameters<typeof fn> (which is itself a tuple), so each argument gets its own options.
respectBinarySize / binarySizingOptionsSteer a value to fit, or deliberately exceed, the binary encoder's cold-start size estimate.
seedFix the random source so the same seed always produces the same value. See below.

For realistic, believable values (real names, your own domains, sensible ranges) instead of mechanical ones, reach for the data enrichment map on the MockData page.

Reproducible data with a seed

By default every call returns fresh random data. Pass a seed and the same seed always produces the same value, for every type, so snapshot tests and fixtures stay stable from one run to the next. Leave the seed out and you get random data again.

// Pass a seed for reproducible data: the same seed always yields the same value,
// so snapshot tests and fixtures stay stable. Leave it out for fresh data.
const mockFixture = createMockDataFn<Account>(undefined, {mock: {seed: 123}});
const sameEveryRun = mockFixture(); // identical on every run

Time-based values (Date, Temporal, and uuid v7) are reproducible under a seed too: the generator anchors them to a fixed reference instant instead of the wall clock (which moves every run), so the same seed reproduces the same values. They are still varied, just deterministic.

Generate invalid data

Flip the generator with invalid: true and you get the opposite of a mock: a value that FAILS validation. It builds a valid value first, then replaces one field with a value of the wrong type. Reach for it to test the unhappy path (your validators, decoders, and error handling) without writing broken fixtures by hand.

// `invalid: true` flips the generator: instead of a valid User it returns one
// with a single field replaced by a value of the wrong type, so it FAILS the
// validator. Great for testing the unhappy path without writing broken fixtures.
const mockBadUser = createMockDataFn<User>(undefined, {mock: {invalid: true}});

const isUser = createValidateFn<User>();
isUser(mockBadUser()); // false  (e.g. {id: 7, email: 12345, role: 'editor', active: true})

// invalidLeafProbability (0 to 1) steers where the bad value lands: 1 always
// corrupts a single deep field, 0 replaces the whole value. Defaults to 0.85.
const mockBadField = createMockDataFn<User>(undefined, {mock: {invalid: true, invalidLeafProbability: 1}});

The invalidLeafProbability knob (0 to 1) steers how deep the bad value lands. Every position is a candidate: the whole value, any nested object or array on any branch, and every leaf field. Near the default of 0.85 it corrupts a single deep field, so the value stays realistic and only one thing is wrong. Lower it and the break tends to move outward, landing on an intermediate object or array, or the whole value. At 0 it always replaces the whole value, at 1 it always breaks a leaf.

Format-aware mocks

If your type uses type formats, the mock respects them. An email field gets a real-looking address, and a uuidv4 field gets a real-looking UUID, not just random characters.

const mockContact = createMockDataFn<Contact>();

const fake = mockContact();
// id is a real-looking UUID, email is a real-looking address —
// not just random strings. The mock is format-aware.
// {id: '3f2504e0-4f89-...', email: 'name@example.com', name: '...'}

This means a mocked value passes not just the structural validator but the format checks too. That is a guarantee, not a best effort: a mock always satisfies the type's own validator. When it cannot (for example when every sample supplied for a custom pattern violates the declared length bounds), the mock function throws a clear error naming the problem instead of quietly returning an invalid value.

A few more format behaviours the mocks follow:

  • A format restricted to a fixed set with allowedValues (the domain formats included) mocks from that allowed set.
  • Case transforms like TF.Lowercase are applied to the mock whenever your program also creates the matching transform with createFormatTransformFn.
  • Two formats that differ only in their mock samples are distinct types, and each one mocks from its own samples.

The full list of formats and how each one mocks lives in Type Formats.

Copyright © 2026