ts-chas/guard exposes two async methods for producing valid test data: .generate() for quick sampling and .arbitrary() for deep integration with fast-check. Both are derived directly from the guard’s constraint chain, so the same guard that validates your data also drives its generation. No separate schemas or factory functions to maintain.
fast-check is a peer dependency and must be installed separately:
.generate()
Promise<T> when called with no argument, or Promise<T[]> when called with a count. Generated values are guaranteed to pass the guard’s predicate.
Quick examples
Data-driven tests with it.each
A common pattern is to generate a batch of valid inputs and feed them to parameterized tests:
.arbitrary()
Promise<Arbitrary<T>> — a fully configured fast-check Arbitrary that you can compose, transform, and use directly in fc.assert property tests.
Property-based testing
Composing arbitraries
Because.arbitrary() returns a standard fast-check Arbitrary, you can use .map(), .filter(), and .chain() on it:
Combining multiple guards
Constraint coverage
The generator reads constraints from the guard’s accumulated metadata and translates them to tight arbitraries. What follows is a full reference for every supported helper.Strings
Numbers
BigInts
BigInt has no native JSON Schema representation, so constraints are stored as internal markers.Booleans
Dates
Dates are always generated within the year range 1000-9000 by default, so
.toISOString() never throws.
URLs
is.url() returns a URL guard (not a string guard). Constraints from URL helpers are reflected in generation:
Arrays
Tuples
Fixed-position tuples generate the correct type at each index:Objects
Shaped objects generate a value for every key in the schema. Optional and nullable fields are handled automatically:Records
is.record(keyGuard, valueGuard) generates plain objects whose keys satisfy keyGuard and whose values satisfy valueGuard:
Maps and Sets
fc.uniqueArray internally so size constraints are always satisfied even after deduplication.
Unions, intersections, and discriminated unions
Fallback behavior
Guards that cannot be mapped to a specific arbitrary fall back tofc.anything(). This covers custom guards created with .where(), .and(), lazy guards, and any other guard whose structure is opaque to the generator. These will produce values that may or may not pass the guard; use .arbitrary() and add a .filter(guard) step if you need guaranteed correctness for custom predicates:
Combining with property-based testing
.arbitrary() slots directly into fc.property for full property-based test suites:
Implementation notes
fast-checkis loaded lazily on the first call to.generate()or.arbitrary(). If it is not installed, a clear error is thrown with installation instructions.- The generator reads from
guard.meta.jsonSchema, the same accumulated metadata object that drives.toJsonSchema(). Adding a constraint to a guard automatically affects both JSON Schema output and data generation. - Constraint chaining composes correctly:
is.number.int.positive.lte(100)generates integers in[1, 100]because each helper merges its contribution into the shared metadata object. - Dates are clamped to the year range 1000-9000 by default to prevent
toISOString()from throwing on extreme values. Explicit.after()or.before()bounds override the defaults.