Introduction to Arbitraries
Relevant source files
The following files were used as context for generating this wiki page:- CONTRIBUTING.md
- packages/fast-check/CHANGELOG_0.X.md
- packages/fast-check/MIGRATION_2.X_TO_3.X.md
- packages/fast-check/package.json
- packages/fast-check/test/e2e/documentation/Docs.md.spec.ts
- website/blog/2023-05-30-whats-new-in-fast-check-3-10-0/index.md
- website/blog/2024-03-04-whats-new-in-fast-check-3-16-0/index.md
- website/blog/2024-04-28-whats-new-in-fast-check-3-18-0/index.md
- website/blog/2025-03-10-whats-new-in-fast-check-4-0-0/index.md
- website/blog/2025-12-15-whats-new-in-fast-check-4-4-0/index.md
Arbitraries are the core building block in fast-check. They are responsible for generating random values to be used in property-based tests and for "shrinking" those values towards a minimal failing case when a property fails. The primary objective of fast-check is to make property-based testing accessible, and arbitraries are the fundamental tool for achieving this by providing a powerful yet simple way to define data generators for any data type.
The library provides a rich set of built-in arbitraries for common JavaScript types and structures. It also offers combiners to create more complex and custom arbitraries from simpler ones. The design of arbitraries has evolved significantly, particularly between versions 2.x and 3.x, to provide a more unified, extensible, and powerful API.
Sources: CONTRIBUTING.md:14, website/blog/2023-05-16-fast-check-loves-docusaurus/index.md:15-17
Core Concepts
An Arbitrary is an object that knows how to generate and shrink values of a specific type. The modern Arbitrary API (standard since v3.x, formerly NextArbitrary in v2.x) is central to the framework's operation.
This diagram shows the conceptual interface of a modern Arbitrary.
generate(mrng, biasFactor): Produces a random value of typeT, along with a context to be used for shrinking. It uses a mutable random number generator (mrng).canShrinkWithoutContext(value): Checks if a value can be shrunk without a context.shrink(value, context): Takes a value and its context, and returns aStreamof smaller or simpler values of the same type.
This API replaced a legacy version to provide more robust shrinking capabilities and a more consistent internal structure.
Sources: packages/fast-check/MIGRATION_2.X_TO_3.X.md:200-209
Built-in Arbitraries
fast-check comes with a wide array of pre-defined arbitraries to cover most common data generation needs.
| Arbitrary Category | Examples | Description | Sources |
|---|---|---|---|
| Primitives | fc.integer(), fc.float(), fc.double(), fc.string(), fc.boolean() | Generate basic JavaScript primitive values. | packages/fast-check/CHANGELOG_0.X.md:94-95 |
| Strings | fc.string(), fc.stringMatching() | Generate strings. string() is a unified builder, while stringMatching() uses a regex. | website/blog/2025-03-10-whats-new-in-fast-check-4-0-0/index.md:26-29, website/blog/2023-05-30-whats-new-in-fast-check-3-10-0/index.md:10-12 |
| Collections | fc.array(), fc.tuple(...), fc.set(), fc.map() | Generate collections of values. set and map were added in v4.4.0. | website/blog/2025-12-15-whats-new-in-fast-check-4-4-0/index.md:10,21 |
| Objects | fc.object(), fc.dictionary(), fc.record() | Generate plain JavaScript objects with various key and value types. | packages/fast-check/CHANGELOG_0.X.md:22-23, website/blog/2025-12-15-whats-new-in-fast-check-4-4-0/index.md:32-34 |
| Recursive | fc.letrec() | Generate recursive data structures like trees or linked lists. | packages/fast-check/MIGRATION_2.X_TO_3.X.md:162-171 |
| Specialized | fc.date(), fc.uuid(), fc.webPath() | Generate specific data formats. | website/blog/2025-03-10-whats-new-in-fast-check-4-0-0/index.md:20-21,50, website/blog/2024-04-28-whats-new-in-fast-check-3-18-0/index.md:25-29 |
Smarter Defaults
A key philosophy is to provide "smarter defaults" that challenge code with edge cases automatically. For instance:
fc.date()now includes invalid dates by default.fc.object()andfc.record()may generate objects with anullprototype.fc.float()andfc.double()generate special values likeNaN,+/-Infinity, and-0by default.
This approach aims to uncover bugs related to edge cases without requiring explicit configuration from the user.
Sources: website/blog/2025-03-10-whats-new-in-fast-check-4-0-0/index.md:20-25, packages/fast-check/MIGRATION_2.X_TO_3.X.md:133-146
Configuring Arbitraries
Unified Signatures
A major change in v3 was the unification of arbitrary signatures to use a single constraints object for configuration. This makes the API more consistent and extensible.
This diagram shows the migration from the old, multi-argument signature to the new, object-based signature.
The following table illustrates this change for some common arbitraries.
| Arbitrary | Old Signature (pre-v3) | New Signature (v3+) |
|---|---|---|
array | array(arb, minLength, maxLength) | array(arb, {minLength, maxLength}) |
string | string(minLength, maxLength) | string({minLength, maxLength}) |
integer | integer(min, max) | integer({min, max}) |
double | double(min, max) | double({min, max}) |
This change was introduced in fast-check@2.4.0 and became the only supported signature in v3.0.0.
Sources: packages/fast-check/MIGRATION_2.X_TO_3.X.md:18-47
Common Configuration Options
min/max: For numerical arbitraries.minLength/maxLength: For arrays and strings.size: A hint to generate smaller or larger values, independent ofmaxLength.noNaN: For floating-point arbitraries, to excludeNaN.noInteger: For floating-point arbitraries, to exclude whole numbers.
Sources: packages/fast-check/MIGRATION_2.X_TO_3.X.md:188-195, website/blog/2024-04-28-whats-new-in-fast-check-3-18-0/index.md:13-15
Creating Custom Arbitraries
While fast-check offers many built-in options, creating custom arbitraries is often necessary.
By Combining Existing Arbitraries
The most common method is to combine one or more existing arbitraries using methods like .map() or fc.tuple().
The following example shows how to build an IPv4 address generator by combining fc.nat and fc.tuple.
const ipV4Arbitrary = fc
.tuple(fc.nat({ max: 255 }), fc.nat({ max: 255 }), fc.nat({ max: 255 }), fc.nat({ max: 255 }))
.map(([a, b, c, d]) => `${a}.${b}.${c}.${d}`);
Alternatively, with the stringMatching arbitrary, this can be simplified using a regular expression:
const ipV4Arbitrary = fc.stringMatching(
/^(?:\d|[1-9]\d|1\d\d|2[0-5]\d)\.(?:\d|[1-9]\d|1\d\d|2[0-5]\d)\.(?:\d|[1-9]\d|1\d\d|2[0-5]\d)\.(?:\d|[1-9]\d|1\d\d|2[0-5]\d)$/,
);
Sources: website/blog/2023-05-30-whats-new-in-fast-check-3-10-0/index.md:16-24
By Implementing the Arbitrary Class
For advanced use cases requiring full control over generation and shrinking, you can implement the Arbitrary<T> class directly. This is the process followed when contributing a new core arbitrary to the fast-check library itself. The process involves defining the generate, canShrinkWithoutContext, and shrink methods.
The contribution guide outlines the steps for adding a new arbitrary, which includes coding the arbitrary, adding unit and integration tests, and documenting it.
Sources: CONTRIBUTING.md:73-81, packages/fast-check/MIGRATION_2.X_TO_3.X.md:200-209
Arbitrary API Evolution
The Arbitrary API has undergone significant evolution, with many legacy features being deprecated and removed in v3.0 and v4.0 to create a more consistent and maintainable codebase.
Deprecated Arbitraries
Several arbitraries were renamed or replaced for clarity and consistency.
| Deprecated Arbitrary | Replacement | Rationale |
|---|---|---|
jsonObject | jsonValue | jsonValue is a more accurate name. |
set | uniqueArray | The original set returned an array, not a Set object. A new fc.set was later introduced in v4.4.0. |
frequency | oneof | oneof provides a more general and powerful way to combine arbitraries with weights. |
stringOf, char16bits, etc. | string | All string arbitraries were consolidated into a single, more powerful fc.string builder in v4.0. |
Sources: packages/fast-check/MIGRATION_2.X_TO_3.X.md:100-111, website/blog/2025-03-10-whats-new-in-fast-check-4-0-0/index.md:26-29
Deprecated Methods
.noShrink(): This method to disable shrinking on an arbitrary was removed..noBias(): This method to disable biasing was removed.
Sources: packages/fast-check/MIGRATION_2.X_TO_3.X.md:49,71, website/blog/2025-03-10-whats-new-in-fast-check-4-0-0/index.md:48,62
Summary
Arbitraries are the foundation of fast-check, providing a declarative and composable way to define test data generators. They encapsulate the logic for both random value generation and shrinking, which is crucial for effective property-based testing. The evolution of the arbitrary API towards unified signatures, smarter defaults, and a consolidated set of core generators has made the library more powerful, consistent, and easier to use for both new and advanced users.
Sources: CONTRIBUTING.md:14, website/blog/2025-03-10-whats-new-in-fast-check-4-0-0/index.md:16-18