All free skills / Other majors
fast-check 4.x
Use fast-check 4.x for property-based testing in standalone JavaScript/TypeScript scripts, with v3-to-v4 migration guidance and runnable Bun examples.
- For
fast-check@4.9.0- Verified
- 2026-09-08, 7 examples executed
- Skill package
@modootoday/pmcp-fast-check@4.0.0
Use this skill for free
No PMCP login or subscription is required. Download the original instructions, or install the content-only archive with your project's package manager.
Download SKILL.md · Download package archive
npm install --save-dev https://pmcp.build/skills/fast-check/4/package.tgz
PMCP discovers the installed package's instructions. Connect your runtime after installation.
Archive integrity
sha512-9o3SYTQSS//t1QkBNJ+hBzKBgojsVgdYIs9YVRA9dIcAow20NFilYd+BJE3FemrKBJo71t4bkQXgChoQ5TcXEA==Complete instructions
Verified against fast-check@4.9.0 on 2026-09-08. 7 of 7 examples executed.
fast-check 4.x
fast-check is a property-based testing library for JavaScript and TypeScript. This skill targets ^4.0.0.
Runtime and language requirements
- Node.js must be at least
12.17.0. - v4 targets ECMAScript 2020.
- TypeScript support is documented for TypeScript
5.0or newer. - Import the package as a namespace:
import * as fc from 'fast-check';
import assert from 'node:assert/strict';
const values = fc.sample(fc.nat(), 10);
assert.equal(values.length, 10);
assert.ok(values.every((value) => Number.isInteger(value) && value >= 0));
Properties, preconditions, and assertions
Build a property with fc.property(arbitrary1, arbitrary2, predicate), then run it with fc.assert. The predicate receives generated values and must return a truthy result. fc.pre(condition) discards a generated case when the precondition is not met; it is useful when the property only applies to part of an arbitrary's domain.
fc.assert throws when the property fails. It is synchronous for synchronous properties.
import * as fc from 'fast-check';
import assert from 'node:assert/strict';
function crop(text: string, maxLength: number): string {
return text.slice(0, maxLength);
}
fc.assert(
fc.property(fc.nat(), fc.string(), (maxLength, label) => {
fc.pre(label.length <= maxLength);
return crop(label, maxLength) === label;
}),
{ seed: 42, numRuns: 20 },
);
assert.ok(true);
Use fc.asyncProperty for asynchronous predicates. Await fc.assert; otherwise a rejected promise can escape the intended control flow.
import * as fc from 'fast-check';
import assert from 'node:assert/strict';
const property = fc.asyncProperty(fc.nat(), async (value) => {
await Promise.resolve();
return value >= 0;
});
await fc.assert(property, { seed: 42, numRuns: 10 });
assert.ok(true);
Inspecting runs with check
fc.check returns RunDetails instead of throwing immediately. The documented v4 result exposes errorInstance when a predicate fails; do not use the v3-shaped error field. Async checks must be awaited.
import * as fc from 'fast-check';
import assert from 'node:assert/strict';
const details = fc.check(
fc.property(fc.constant(1), (value) => value === 1),
{ numRuns: 1, seed: 42 },
);
assert.equal(details.failed, false);
assert.equal(details.numRuns, 1);
const asyncDetails = await fc.check(
fc.asyncProperty(fc.constant('ok'), async (value) => {
await Promise.resolve();
return value === 'ok';
}),
{ numRuns: 1, seed: 42 },
);
assert.equal(asyncDetails.failed, false);
Sampling arbitraries
fc.sample(arbitrary, count) extracts generated values. Passing { seed } samples as though the run used that seed. The result is an array of generated values.
import * as fc from 'fast-check';
import assert from 'node:assert/strict';
const tenNaturals = fc.sample(fc.nat(), 10);
assert.equal(tenNaturals.length, 10);
assert.ok(tenNaturals.every((value) => value >= 0));
const first = fc.sample(fc.nat(), { seed: 42 });
const second = fc.sample(fc.nat(), { seed: 42 });
assert.deepEqual(first, second);
Global configuration
fc.configureGlobal(parameters) changes default parameters used by subsequent operations, such as numRuns. A per-call parameter still applies to that call and can override the global setting. In a test framework, global configuration is typically placed in that framework's setup file; a standalone script can call it directly.
import * as fc from 'fast-check';
import assert from 'node:assert/strict';
fc.configureGlobal({ numRuns: 10 });
const details = fc.check(
fc.property(fc.nat(), fc.nat(), (a, b) => a + b === b + a),
{ seed: 42 },
);
assert.equal(details.failed, false);
assert.equal(details.numRuns, 10);
Common arbitraries and v4 inference
The documented API includes anything, array, boolean, constant, constantFrom, nat, object, oneof, record, string, and tuple, among others. constant and constantFrom have improved literal inference in v4: for example, fc.constant('a') is an Arbitrary<'a'>, and fc.constantFrom('a', 'b') is an Arbitrary<'a' | 'b'>.
import * as fc from 'fast-check';
import assert from 'node:assert/strict';
const literal = fc.constant('a');
const choice = fc.constantFrom('a', 'b');
const pair = fc.tuple(fc.boolean(), fc.nat());
const objectValue = fc.record({ name: fc.string(), enabled: fc.boolean() });
assert.equal(fc.sample(literal, 1)[0], 'a');
assert.ok(fc.sample(choice, 20).every((value) => value === 'a' || value === 'b'));
assert.equal(fc.sample(pair, 1)[0].length, 2);
assert.equal(typeof fc.sample(objectValue, 1)[0].enabled, 'boolean');
v3-to-v4 migration traps
Do not copy older v3 examples without checking their options and names.
- Valid-only dates are no longer the default. Use
fc.date({ noInvalidDate: true })to preserve the v3 behavior. - Dictionaries and records no longer use the old default prototype behavior. Use
{ noNullPrototype: true }withfc.dictionaryorfc.recordto preserve the v3 behavior. - UUID generation changed defaults. Use
fc.uuid({ version: [1, 2, 3, 4, 5] })to preserve v3 UUID versions. - Replace
fc.record(model, { withDeletedKeys: true })withfc.record(model, { requiredKeys: [] }). - Removed or deprecated v3 names include
uuidV,unicodeJson*,ascii*,hexa*,base64,stringOf,char16bits,string16bits,fullUnicode*,unicode*,char,bigIntN,bigUintN,bigUint, and.noShrink. - Use
fc.noShrink(myArbitrary)rather than the removed.noShrinkshape. - Use
fc.string({ unit: fc.constantFrom('Hello', 'World') })rather than the removed string helpers. - For bounded big integers, use
fc.bigInt({ min: 0n, max: (1n << BigInt(n)) - 1n }). - Predicate errors now retain the original error as
cause. If v3-style reporting is required, useincludeErrorInReport. - Custom property runners must explicitly call
runBeforeEachandrunAfterEach. - Custom
Arbitraryimplementations must not use the removedRandom.nextArrayInt.
What this skill does not cover
This skill does not cover every arbitrary, matcher, class, custom Arbitrary implementation, runner integration, or framework-specific setup API. It does not cover the complete Random, Stream, Value, or Arbitrary class APIs, advanced shrinking, failure-report formatting, or the full Parameters and RunDetails type definitions. fast-check is runner-agnostic; framework hooks and test-runner configuration are outside the documented standalone examples here.