Repository: dubzzz/fast-check
Pull request #2921 (2022-05-05 16:31:09)

♻️ Replace deprecated usages of `integer` by constraint-based ones
<!-- Context of the PR: short description and potentially linked issues -->

<!-- ...a few words to describe the content of this PR...               -->
<!-- ... -->

<!-- Type of PR: [ ] unchecked / [ ] checked -->
**_Category:_**

- [ ] ✨ Introduce new features
- [ ] 📝 Add or update documentation
- [ ] ✅ Add or update tests
- [ ] 🐛 Fix a bug
- [ ] 🏷️ Add or update types
- [ ] ⚡️ Improve performance
- [ ] _Other(s):_ ...
<!-- Don't forget to add the gitmoji icon in the name of the PR -->
<!-- See: https://gitmoji.dev/                                  -->

<!-- Fixing bugs, adding features... may impact existing ones           -->
<!-- in order to track potential issues that could be related to your PR -->
<!-- please check the impacts and describe more precisely what to expect -->

**_Potential impacts:_**

<!-- Generated values: Can your change impact any of the existing generators in terms of generated values, if so which ones? when? -->
<!-- Shrink values:    Can your change impact any of the existing generators in terms of shrink values, if so which ones? when? -->
<!-- Performance:      Can it require some typings changes on user side? Please give more details -->
<!-- Typings:          Is there a potential performance impact? In which cases? -->
- [ ] Generated values
- [ ] Shrink values
- [ ] Performance
- [ ] Typings
- [ ] _Other(s):_ ...


codesandbox[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/dubzzz/fast-check/pr/2921/builds/247091) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 3ced54a4e610ab44ac665ffe1806feb9a6823ff1:

|Sandbox| Source |
|--|--|
|[Vanilla](https://codesandbox.io/s/vanilla-m2qqix)| Configuration |
|[fast-check-examples](https://codesandbox.io/s/fast-check-examples-m2tc6i)| Configuration |


Patch:
diff --git a/documentation/Arbitraries.md b/documentation/Arbitraries.md
index 4ea0746b..9b341e89 100644
--- a/documentation/Arbitraries.md
+++ b/documentation/Arbitraries.md
@@ -3139,6 +3139,72 @@ fc.jsonValue({maxDepth: 0})
 
 fc.jsonValue({maxDepth: 1})
 // Examples of generated values: [], -1.2e-322, "W!oe%r(", {}, [false,"?Y]}I%d",2.7395116183994342e+35]…
+
+fc.statistics(
+  fc.jsonValue(),
+  v => {
+    function size(n) {
+      if (Array.isArray(n))
+        return 1 + n.reduce((acc, child) => acc + size(child), 0);
+      if (typeof n === "object" && n)
+        return 1 + Object.values(n).reduce((acc, child) => acc + size(child), 0);
+      return 1;
+    }
+    const s = size(v);
+    let lower = 1;
+    const next = n => String(n)[0] === '1' ? n * 5 : n * 2;
+    while (next(lower) <= s) { lower = next(lower); }
+    return `${lower} to ${next(lower) -1} items`;
+  }
+)
+// Note: In version 2.x, the depth of objects-like arbitraries is by default limited to 2.
+// It will not be the case anymore starting at version 3.x. In 3.x, the default maximal depth
+// will be unset meaning it can theoretically reach infinity. 'theoretically' as depth factor
+// will prevent that from occuring.
+// Computed statistics for 10k generated values:
+// For size = "xsmall":
+// • 1 to 4 items....73.30%
+// • 5 to 9 items....26.42%
+// • 10 to 49 items...0.28%
+// For size = "small":
+// • 1 to 4 items....66.73%
+// • 5 to 9 items....31.79%
+// • 10 to 49 items...1.48%
+// For size = "medium":
+// • 1 to 4 items....66.91%
+// • 5 to 9 items....31.75%
+// • 10 to 49 items...1.34%
+
+fc.statistics(
+  fc.jsonValue({maxDepth: 2}),
+  v => {
+    function size(n) {
+      if (Array.isArray(n))
+        return 1 + n.reduce((acc, child) => acc + size(child), 0);
+      if (typeof n === "object" && n)
+        return 1 + Object.values(n).reduce((acc, child) => acc + size(child), 0);
+      return 1;
+    }
+    const s = size(v);
+    let lower = 1;
+    const next = n => String(n)[0] === '1' ? n * 5 : n * 2;
+    while (next(lower) <= s) { lower = next(lower); }
+    return `${lower} to ${next(lower) -1} items`;
+  }
+)
+// Computed statistics for 10k generated values:
+// For size = "xsmall":
+// • 1 to 4 items....73.34%
+// • 5 to 9 items....26.32%
+// • 10 to 49 items...0.34%
+// For size = "small":
+// • 1 to 4 items....66.98%
+// • 5 to 9 items....31.53%
+// • 10 to 49 items...1.49%
+// For size = "medium":
+// • 1 to 4 items....66.94%
+// • 5 to 9 items....31.55%
+// • 10 to 49 items...1.51%
 ```
 </details>
 
diff --git a/example/001-simple/decompPrime/main.spec.ts b/example/001-simple/decompPrime/main.spec.ts
index da0c2cab..64e89f80 100644
--- a/example/001-simple/decompPrime/main.spec.ts
+++ b/example/001-simple/decompPrime/main.spec.ts
@@ -17,7 +17,7 @@ describe('decompPrime', () => {
 
   it('should be able to decompose a product of two numbers', () => {
     fc.assert(
-      fc.property(fc.integer(2, MAX_INPUT), fc.integer(2, MAX_INPUT), (a, b) => {
+      fc.property(fc.integer({ min: 2, max: MAX_INPUT }), fc.integer({ min: 2, max: MAX_INPUT }), (a, b) => {
         const n = a * b;
         const factors = decompPrime(n);
         return factors.length >= 2;
@@ -27,7 +27,7 @@ describe('decompPrime', () => {
 
   it('should compute the same factors as to the concatenation of the one of a and b for a times b', () => {
     fc.assert(
-      fc.property(fc.integer(2, MAX_INPUT), fc.integer(2, MAX_INPUT), (a, b) => {
+      fc.property(fc.integer({ min: 2, max: MAX_INPUT }), fc.integer({ min: 2, max: MAX_INPUT }), (a, b) => {
         const factorsA = decompPrime(a);
         const factorsB = decompPrime(b);
         const factorsAB = decompPrime(a * b);
diff --git a/example/001-simple/fibonacci/main.spec.ts b/example/001-simple/fibonacci/main.spec.ts
index 2f95c045..7e4c24a8 100644
--- a/example/001-simple/fibonacci/main.spec.ts
+++ b/example/001-simple/fibonacci/main.spec.ts
@@ -8,7 +8,7 @@ const MaxN = 1000;
 describe('fibonacci', () => {
   it('should be equal to the sum of fibo(n-1) and fibo(n-2)', () => {
     fc.assert(
-      fc.property(fc.integer(2, MaxN), (n) => {
+      fc.property(fc.integer({ min: 2, max: MaxN }), (n) => {
         expect(fibo(n)).toBe(fibo(n - 1) + fibo(n - 2));
       })
     );
@@ -19,7 +19,7 @@ describe('fibonacci', () => {
 
   it('should fulfill fibo(p)*fibo(q+1)+fibo(p-1)*fibo(q) = fibo(p+q)', () => {
     fc.assert(
-      fc.property(fc.integer(1, MaxN), fc.integer(0, MaxN), (p, q) => {
+      fc.property(fc.integer({ min: 1, max: MaxN }), fc.integer({ min: 0, max: MaxN }), (p, q) => {
         expect(fibo(p + q)).toBe(fibo(p) * fibo(q + 1) + fibo(p - 1) * fibo(q));
       })
     );
@@ -28,7 +28,7 @@ describe('fibonacci', () => {
   it('should fulfill fibo(2p-1) = fibo²(p-1)+fibo²(p)', () => {
     // Special case of the property above
     fc.assert(
-      fc.property(fc.integer(1, MaxN), (p) => {
+      fc.property(fc.integer({ min: 1, max: MaxN }), (p) => {
         expect(fibo(2 * p - 1)).toBe(fibo(p - 1) * fibo(p - 1) + fibo(p) * fibo(p));
       })
     );
@@ -36,7 +36,7 @@ describe('fibonacci', () => {
 
   it('should fulfill Catalan identity', () => {
     fc.assert(
-      fc.property(fc.integer(0, MaxN), fc.integer(0, MaxN), (a, b) => {
+      fc.property(fc.integer({ min: 0, max: MaxN }), fc.integer({ min: 0, max: MaxN }), (a, b) => {
         const [p, q] = a < b ? [b, a] : [a, b];
         const sign = (p - q) % 2 === 0 ? 1n : -1n; // (-1)^(p-q)
         expect(fibo(p) * fibo(p) - fibo(p - q) * fibo(p + q)).toBe(sign * fibo(q) * fibo(q));
@@ -46,7 +46,7 @@ describe('fibonacci', () => {
 
   it('should fulfill Cassini identity', () => {
     fc.assert(
-      fc.property(fc.integer(1, MaxN), fc.integer(0, MaxN), (p) => {
+      fc.property(fc.integer({ min: 1, max: MaxN }), (p) => {
         const sign = p % 2 === 0 ? 1n : -1n; // (-1)^p
         expect(fibo(p + 1) * fibo(p - 1) - fibo(p) * fibo(p)).toBe(sign);
       })
@@ -55,7 +55,7 @@ describe('fibonacci', () => {
 
   it('should fibo(nk) divisible by fibo(n)', () => {
     fc.assert(
-      fc.property(fc.integer(1, MaxN), fc.integer(0, 100), (n, k) => {
+      fc.property(fc.integer({ min: 1, max: MaxN }), fc.integer({ min: 0, max: 100 }), (n, k) => {
         expect(fibo(n * k) % fibo(n)).toBe(0n);
       })
     );
@@ -63,7 +63,7 @@ describe('fibonacci', () => {
 
   it('should fulfill gcd(fibo(a), fibo(b)) = fibo(gcd(a,b))', () => {
     fc.assert(
-      fc.property(fc.integer(1, MaxN), fc.integer(1, MaxN), (a, b) => {
+      fc.property(fc.integer({ min: 1, max: MaxN }), fc.integer({ min: 1, max: MaxN }), (a, b) => {
         const gcd = <T extends bigint | number>(a: T, b: T, zero: T): T => {
           a = a < zero ? (-a as T) : a;
           b = b < zero ? (-b as T) : b;
diff --git a/example/002-recursive/isSearchTree/arbitraries/BinarySearchTreeArbitrary.ts b/example/002-recursive/isSearchTree/arbitraries/BinarySearchTreeArbitrary.ts
index 7a3d6113..5b8d9ffc 100644
--- a/example/002-recursive/isSearchTree/arbitraries/BinarySearchTreeArbitrary.ts
+++ b/example/002-recursive/isSearchTree/arbitraries/BinarySearchTreeArbitrary.ts
@@ -4,7 +4,7 @@ import { Tree } from '../src/isSearchTree';
 export const binarySearchTreeWithMaxDepth = (maxDepth: number): fc.Arbitrary<Tree<number>> => {
   const leaf = (minValue: number, maxValue: number): fc.Arbitrary<Tree<number>> =>
     fc.record({
-      value: fc.integer(minValue, maxValue),
+      value: fc.integer({ min: minValue, max: maxValue }),
       left: fc.constant(null),
       right: fc.constant(null),
     });
@@ -12,7 +12,7 @@ export const binarySearchTreeWithMaxDepth = (maxDepth: number): fc.Arbitrary<Tre
   const node = (minValue: number, maxValue: number): fc.Memo<Tree<number>> =>
     fc.memo((n) => {
       if (n <= 1) return leaf(minValue, maxValue);
-      return fc.integer(minValue, maxValue).chain((v) => {
+      return fc.integer({ min: minValue, max: maxValue }).chain((v) => {
         // tree(minValue, v)(n - 1) is equivalent to tree(minValue, v)()
         return fc.record({
           value: fc.constant(v),
@@ -33,7 +33,7 @@ export const binarySearchTreeWithMaxDepthOldWay = (
   minValue: number = Number.MIN_SAFE_INTEGER,
   maxValue: number = Number.MAX_SAFE_INTEGER
 ): fc.Arbitrary<Tree<number>> => {
-  const valueArbitrary = fc.integer(minValue, maxValue);
+  const valueArbitrary = fc.integer({ min: minValue, max: maxValue });
   if (maxDepth <= 0) {
     return fc.record({
       value: valueArbitrary,
diff --git a/example/003-misc/knight/arbitraries/SpaceArbitrary.ts b/example/003-misc/knight/arbitraries/SpaceArbitrary.ts
index 379c57b7..47793f01 100644
--- a/example/003-misc/knight/arbitraries/SpaceArbitrary.ts
+++ b/example/003-misc/knight/arbitraries/SpaceArbitrary.ts
@@ -3,12 +3,12 @@ import { SpaceBuilder, Space } from '../src/space';
 
 export const SpaceArbitrary = fc
   .record({
-    w: fc.integer(1, 1000),
-    h: fc.integer(1, 1000),
-    cx: fc.integer(1, 1000),
-    cy: fc.integer(1, 1000),
-    sx: fc.integer(1, 1000),
-    sy: fc.integer(1, 1000),
+    w: fc.integer({ min: 1, max: 1000 }),
+    h: fc.integer({ min: 1, max: 1000 }),
+    cx: fc.integer({ min: 1, max: 1000 }),
+    cy: fc.integer({ min: 1, max: 1000 }),
+    sx: fc.integer({ min: 1, max: 1000 }),
+    sy: fc.integer({ min: 1, max: 1000 }),
   })
   .filter(({ w, h, cx, cy, sx, sy }) => cx < w && sx < w && cy < h && sy < h)
   .map(({ w, h, cx, cy, sx, sy }) =>
diff --git a/example/003-misc/mazeGenerator/main.spec.ts b/example/003-misc/mazeGenerator/main.spec.ts
index 3aef1488..0bc215e9 100644
--- a/example/003-misc/mazeGenerator/main.spec.ts
+++ b/example/003-misc/mazeGenerator/main.spec.ts
@@ -107,8 +107,8 @@ describe('mazeGenerator', () => {
 const seedArb = fc.integer().noBias().noShrink();
 
 const dimensionArb = fc.record({
-  width: fc.integer(2, 20),
-  height: fc.integer(2, 20),
+  width: fc.integer({ min: 2, max: 20 }),
+  height: fc.integer({ min: 2, max: 20 }),
 });
 
 const inputsArb = dimensionArb
diff --git a/example/003-misc/roman/main.spec.ts b/example/003-misc/roman/main.spec.ts
index 735a01a4..45e6674f 100644
--- a/example/003-misc/roman/main.spec.ts
+++ b/example/003-misc/roman/main.spec.ts
@@ -29,7 +29,7 @@ describe('toRoman', () => {
 
   it('should start negative romans with a minus sign', () => {
     fc.assert(
-      fc.property(fc.integer(-MaxRoman, -1), (n) => {
+      fc.property(fc.integer({ min: -MaxRoman, max: -1 }), (n) => {
         expect(toRoman(n)[0]).toBe('-');
       })
     );
@@ -100,5 +100,5 @@ describe('fromRoman', () => {
 
 // Helpers
 
-const romanNumberArb = fc.integer(-MaxRoman, MaxRoman);
-const posRomanNumberArb = fc.integer(1, MaxRoman);
+const romanNumberArb = fc.integer({ min: -MaxRoman, max: MaxRoman });
+const posRomanNumberArb = fc.integer({ min: 1, max: MaxRoman });
diff --git a/example/005-race/dependencyTree/main.spec.ts b/example/005-race/dependencyTree/main.spec.ts
index 35b7baad..9c76246b 100644
--- a/example/005-race/dependencyTree/main.spec.ts
+++ b/example/005-race/dependencyTree/main.spec.ts
@@ -37,7 +37,7 @@ describe('dependencyTree', () => {
 
 // Helpers
 
-const AllPackagesArbitrary = fc.integer(1, 5).chain((numPackages) => {
+const AllPackagesArbitrary = fc.integer({ min: 1, max: 5 }).chain((numPackages) => {
   const packageNames = [...Array(numPackages)].map((_, id) => `package-${String.fromCharCode('a'.charCodeAt(0) + id)}`);
   return fc
     .genericTuple(
diff --git a/src/arbitrary/_internals/ArrayArbitrary.ts b/src/arbitrary/_internals/ArrayArbitrary.ts
index 2979b80d..04efdc94 100644
--- a/src/arbitrary/_internals/ArrayArbitrary.ts
+++ b/src/arbitrary/_internals/ArrayArbitrary.ts
@@ -41,7 +41,7 @@ export class ArrayArbitrary<T> extends NextArbitrary<T[]> {
     readonly setBuilder?: CustomSetBuilder<NextValue<T>>
   ) {
     super();
-    this.lengthArb = convertToNext(integer(minLength, maxGeneratedLength));
+    this.lengthArb = convertToNext(integer({ min: minLength, max: maxGeneratedLength }));
     this.depthContext = getDepthContextFor(depthIdentifier);
   }
 
@@ -190,7 +190,10 @@ export class ArrayArbitrary<T> extends NextArbitrary<T[]> {
     }
     // We apply bias for both items and length (1 chance over biasFactor²)
     const maxBiasedLength = biasedMaxLength(this.minLength, this.maxGeneratedLength);
-    const targetSizeValue = convertToNext(integer(this.minLength, maxBiasedLength)).generate(mrng, undefined);
+    const targetSizeValue = convertToNext(integer({ min: this.minLength, max: maxBiasedLength })).generate(
+      mrng,
+      undefined
+    );
     return { size: targetSizeValue.value, biasFactorItems: biasFactor };
   }
 
diff --git a/src/arbitrary/_internals/builders/CharacterArbitraryBuilder.ts b/src/arbitrary/_internals/builders/CharacterArbitraryBuilder.ts
index b98a32fb..ca326772 100644
--- a/src/arbitrary/_internals/builders/CharacterArbitraryBuilder.ts
+++ b/src/arbitrary/_internals/builders/CharacterArbitraryBuilder.ts
@@ -11,7 +11,7 @@ export function buildCharacterArbitrary(
   unmapFromCode: (v: number) => number
 ): Arbitrary<string> {
   return convertFromNext(
-    convertToNext(integer(min, max)).map(
+    convertToNext(integer({ min, max })).map(
       (n) => indexToCharStringMapper(mapToCode(n)),
       (c) => unmapFromCode(indexToCharStringUnmapper(c))
     )
diff --git a/src/arbitrary/_internals/builders/CompareFunctionArbitraryBuilder.ts b/src/arbitrary/_internals/builders/CompareFunctionArbitraryBuilder.ts
index 6ce7913f..86fe6037 100644
--- a/src/arbitrary/_internals/builders/CompareFunctionArbitraryBuilder.ts
+++ b/src/arbitrary/_internals/builders/CompareFunctionArbitraryBuilder.ts
@@ -10,7 +10,7 @@ import { tuple } from '../../tuple';
 export function buildCompareFunctionArbitrary<T, TOut>(
   cmp: (hA: number, hB: number) => TOut
 ): Arbitrary<(a: T, b: T) => TOut> {
-  return tuple(integer().noShrink(), integer(1, 0xffffffff).noShrink()).map(([seed, hashEnvSize]) => {
+  return tuple(integer().noShrink(), integer({ min: 1, max: 0xffffffff }).noShrink()).map(([seed, hashEnvSize]) => {
     const producer = () => {
       const recorded: { [key: string]: TOut } = {};
       const f = (a: T, b: T) => {
diff --git a/src/arbitrary/date.ts b/src/arbitrary/date.ts
index 8c932a50..44a18466 100644
--- a/src/arbitrary/date.ts
+++ b/src/arbitrary/date.ts
@@ -18,5 +18,7 @@ export function date(constraints?: { min?: Date; max?: Date }): Arbitrary<Date>
   if (Number.isNaN(intMin)) throw new Error('fc.date min must be valid instance of Date');
   if (Number.isNaN(intMax)) throw new Error('fc.date max must be valid instance of Date');
   if (intMin > intMax) throw new Error('fc.date max must be greater or equal to min');
-  return convertFromNext(convertToNext(integer(intMin, intMax)).map(timeToDateMapper, timeToDateUnmapper));
+  return convertFromNext(
+    convertToNext(integer({ min: intMin, max: intMax })).map(timeToDateMapper, timeToDateUnmapper)
+  );
 }


Test patch:
diff --git a/test/e2e/GenerateAllValues.spec.ts b/test/e2e/GenerateAllValues.spec.ts
index 08fdd884..cbb42f87 100644
--- a/test/e2e/GenerateAllValues.spec.ts
+++ b/test/e2e/GenerateAllValues.spec.ts
@@ -23,7 +23,9 @@ describe(`Generate all values (seed: ${seed})`, () => {
   describe('fc.integer()', () => {
     it('Should be able to produce all integer values within the range', () =>
       fc.assert(
-        fc.property(fc.integer(), fc.nat(100), (from, gap) => lookForMissing(fc.integer(from, from + gap), gap + 1))
+        fc.property(fc.integer(), fc.nat(100), (from, gap) =>
+          lookForMissing(fc.integer({ min: from, max: from + gap }), gap + 1)
+        )
       ));
   });
   describe('fc.char()', () => {
diff --git a/test/e2e/Shadows.spec.ts b/test/e2e/Shadows.spec.ts
index 2408a98f..2fe3e4ba 100644
--- a/test/e2e/Shadows.spec.ts
+++ b/test/e2e/Shadows.spec.ts
@@ -140,12 +140,12 @@ function locateInSpace(space: Space, rounds: number) {
 
 const SpaceArbitrary = fc
   .record({
-    w: fc.integer(1, 1000),
-    h: fc.integer(1, 1000),
-    cx: fc.integer(1, 1000),
-    cy: fc.integer(1, 1000),
-    sx: fc.integer(1, 1000),
-    sy: fc.integer(1, 1000),
+    w: fc.integer({ min: 1, max: 1000 }),
+    h: fc.integer({ min: 1, max: 1000 }),
+    cx: fc.integer({ min: 1, max: 1000 }),
+    cy: fc.integer({ min: 1, max: 1000 }),
+    sx: fc.integer({ min: 1, max: 1000 }),
+    sy: fc.integer({ min: 1, max: 1000 }),
   })
   .filter(({ w, h, cx, cy, sx, sy }) => cx < w && sx < w && cy < h && sy < h)
   .map(({ w, h, cx, cy, sx, sy }) =>
diff --git a/test/e2e/WithProvidedExamples.spec.ts b/test/e2e/WithProvidedExamples.spec.ts
index bf9e5eff..12ce3814 100644
--- a/test/e2e/WithProvidedExamples.spec.ts
+++ b/test/e2e/WithProvidedExamples.spec.ts
@@ -4,7 +4,7 @@ import { seed } from './seed';
 describe(`WithProvidedExamples (seed: ${seed})`, () => {
   it('should fail on one of the provided examples', () => {
     const out = fc.check(
-      fc.property(fc.integer(1, 100), fc.integer(1, 100), (x, y) => x < y),
+      fc.property(fc.integer({ min: 1, max: 100 }), fc.integer({ min: 1, max: 100 }), (x, y) => x < y),
       {
         examples: [
           [1, 2],
@@ -20,7 +20,7 @@ describe(`WithProvidedExamples (seed: ${seed})`, () => {
   });
   it('should fail on one of the provided examples and shrink it', () => {
     const out = fc.check(
-      fc.property(fc.integer(1, 100), fc.integer(1, 100), (x, y) => x < y),
+      fc.property(fc.integer({ min: 1, max: 100 }), fc.integer({ min: 1, max: 100 }), (x, y) => x < y),
       {
         examples: [
           [1, 2],
diff --git a/test/e2e/arbitraries/ArrayArbitrary.spec.ts b/test/e2e/arbitraries/ArrayArbitrary.spec.ts
index 98b8ea96..13c90667 100644
--- a/test/e2e/arbitraries/ArrayArbitrary.spec.ts
+++ b/test/e2e/arbitraries/ArrayArbitrary.spec.ts
@@ -16,7 +16,7 @@ describe(`ArrayArbitrary (seed: ${seed})`, () => {
     });
     it('Should shrink on the content of the array', () => {
       const out = fc.check(
-        fc.property(fc.array(fc.integer(3, 10)), (arr: number[]) => arr.length < 2),
+        fc.property(fc.array(fc.integer({ min: 3, max: 10 })), (arr: number[]) => arr.length < 2),
         { seed: seed }
       );
       expect(out.failed).toBe(true);
@@ -24,7 +24,7 @@ describe(`ArrayArbitrary (seed: ${seed})`, () => {
     });
     it('Should shrink removing unecessary entries in the array', () => {
       const out = fc.check(
-        fc.property(fc.array(fc.integer(0, 10)), (arr: number[]) => arr.filter((v) => v >= 5).length < 2),
+        fc.property(fc.array(fc.integer({ min: 0, max: 10 })), (arr: number[]) => arr.filter((v) => v >= 5).length < 2),
         { seed: seed }
       );
       expect(out.failed).toBe(true);
diff --git a/test/e2e/arbitraries/IntegerArbitrary.spec.ts b/test/e2e/arbitraries/IntegerArbitrary.spec.ts
index 1f2319c1..74ad9278 100644
--- a/test/e2e/arbitraries/IntegerArbitrary.spec.ts
+++ b/test/e2e/arbitraries/IntegerArbitrary.spec.ts
@@ -5,14 +5,14 @@ describe(`IntegerArbitrary (seed: ${seed})`, () => {
   describe('integer', () => {
     it('Should generate integer within the range', () => {
       const out = fc.check(
-        fc.property(fc.integer(-42, -10), (v: number) => -42 <= v && v <= -10),
+        fc.property(fc.integer({ min: -42, max: -10 }), (v: number) => -42 <= v && v <= -10),
         { seed: seed }
       );
       expect(out.failed).toBe(false);
     });
     it('Should shrink integer with strictly negative range', () => {
       const out = fc.check(
-        fc.property(fc.integer(-1000, -10), (v: number) => v > -100),
+        fc.property(fc.integer({ min: -1000, max: -10 }), (v: number) => v > -100),
         { seed: seed }
       );
       expect(out.failed).toBe(true);
diff --git a/test/e2e/arbitraries/OneOfArbitrary.spec.ts b/test/e2e/arbitraries/OneOfArbitrary.spec.ts
index 48a7d3c0..db553add 100644
--- a/test/e2e/arbitraries/OneOfArbitrary.spec.ts
+++ b/test/e2e/arbitraries/OneOfArbitrary.spec.ts
@@ -15,7 +15,12 @@ describe(`OneOfArbitrary (seed: ${seed})`, () => {
     it('Should shrink on the underlying arbitrary', () => {
       const out = fc.check(
         fc.property(
-          fc.oneof(fc.integer(-10, -1), fc.integer(0, 9), fc.integer(10, 19), fc.integer(20, 29)),
+          fc.oneof(
+            fc.integer({ min: -10, max: -1 }),
+            fc.integer({ min: 0, max: 9 }),
+            fc.integer({ min: 10, max: 19 }),
+            fc.integer({ min: 20, max: 29 })
+          ),
           (v: number) => v < 14 || v >= 20
         ),
         { seed: seed }
diff --git a/test/unit/arbitrary/_internals/ArrayArbitrary.spec.ts b/test/unit/arbitrary/_internals/ArrayArbitrary.spec.ts
index 92ce083e..78ea5cde 100644
--- a/test/unit/arbitrary/_internals/ArrayArbitrary.spec.ts
+++ b/test/unit/arbitrary/_internals/ArrayArbitrary.spec.ts
@@ -52,7 +52,7 @@ describe('ArrayArbitrary', () => {
             expect(g.hasToBeCloned).toBe(false);
             expect(g.value).toEqual([...acceptedValues].map((v) => v.value));
             expect(integer).toHaveBeenCalledTimes(1);
-            expect(integer).toHaveBeenCalledWith(minLength, maxGeneratedLength);
+            expect(integer).toHaveBeenCalledWith({ min: minLength, max: maxGeneratedLength });
             expect(generateInteger).toHaveBeenCalledTimes(1);
             expect(generateInteger).toHaveBeenCalledWith(mrng, undefined);
             expect(generate).toHaveBeenCalledTimes(acceptedValues.size);
@@ -92,7 +92,7 @@ describe('ArrayArbitrary', () => {
             // The generator is allowed to stop whenever it considers at already tried to many times (maxGeneratedLength times)
             expect(g.value).toEqual([...acceptedValues].map((v) => v.value).slice(0, g.value.length));
             expect(integer).toHaveBeenCalledTimes(1);
-            expect(integer).toHaveBeenCalledWith(minLength, maxGeneratedLength);
+            expect(integer).toHaveBeenCalledWith({ min: minLength, max: maxGeneratedLength });
             expect(generateInteger).toHaveBeenCalledTimes(1);
             expect(generateInteger).toHaveBeenCalledWith(mrng, undefined);
             expect(setBuilder).toHaveBeenCalledTimes(1);
@@ -149,7 +149,7 @@ describe('ArrayArbitrary', () => {
               );
             }
             expect(integer).toHaveBeenCalledTimes(1);
-            expect(integer).toHaveBeenCalledWith(minLength, minLength);
+            expect(integer).toHaveBeenCalledWith({ min: minLength, max: minLength });
             expect(generateInteger).toHaveBeenCalledTimes(1);
             expect(generateInteger).toHaveBeenCalledWith(mrng, undefined); // no need to bias it
             expect(setBuilder).toHaveBeenCalledTimes(withSetBuilder ? 1 : 0);
diff --git a/test/unit/arbitrary/_internals/builders/TypedIntArrayArbitraryBuilder.spec.ts b/test/unit/arbitrary/_internals/builders/TypedIntArrayArbitraryBuilder.spec.ts
index 327f56df..b6b4e8f0 100644
--- a/test/unit/arbitrary/_internals/builders/TypedIntArrayArbitraryBuilder.spec.ts
+++ b/test/unit/arbitrary/_internals/builders/TypedIntArrayArbitraryBuilder.spec.ts
@@ -208,26 +208,28 @@ function validArrayConstraintsArb() {
 }
 
 function validIntegerConstraintsArb(min: number, max: number) {
-  return fc.record({ min: fc.integer(min, max), max: fc.integer(min, max) }, { withDeletedKeys: true }).map((ct) => {
-    if (ct.min !== undefined && ct.max !== undefined && ct.min > ct.max) {
-      return { min: ct.max, max: ct.min };
-    }
-    return ct;
-  });
+  return fc
+    .record({ min: fc.integer({ min, max }), max: fc.integer({ min, max }) }, { withDeletedKeys: true })
+    .map((ct) => {
+      if (ct.min !== undefined && ct.max !== undefined && ct.min > ct.max) {
+        return { min: ct.max, max: ct.min };
+      }
+      return ct;
+    });
 }
 
 function invalidIntegerConstraintsArb(min: number, max: number) {
   return fc.oneof(
     // min > max
     fc
-      .record({ min: fc.integer(min, max), max: fc.integer(min, max) })
+      .record({ min: fc.integer({ min, max }), max: fc.integer({ min, max }) })
       .filter(({ min, max }) => min !== max)
       .map((ct) => (ct.min < ct.max ? { min: ct.max, max: ct.min } : ct)),
     // min < lowest
-    fc.record({ min: fc.integer(Number.MIN_SAFE_INTEGER, min - 1) }),
-    fc.record({ min: fc.integer(Number.MIN_SAFE_INTEGER, min - 1), max: fc.integer(min, max) }),
+    fc.record({ min: fc.integer({ min: Number.MIN_SAFE_INTEGER, max: min - 1 }) }),
+    fc.record({ min: fc.integer({ min: Number.MIN_SAFE_INTEGER, max: min - 1 }), max: fc.integer({ min, max }) }),
     // max > highest
-    fc.record({ min: fc.integer(min, max), max: fc.integer(max + 1, Number.MAX_SAFE_INTEGER) }),
-    fc.record({ max: fc.integer(max + 1, Number.MAX_SAFE_INTEGER) })
+    fc.record({ min: fc.integer({ min, max }), max: fc.integer({ min: max + 1, max: Number.MAX_SAFE_INTEGER }) }),
+    fc.record({ max: fc.integer({ min: max + 1, max: Number.MAX_SAFE_INTEGER }) })
   );
 }
diff --git a/test/unit/arbitrary/_internals/helpers/BiasNumericRange.spec.ts b/test/unit/arbitrary/_internals/helpers/BiasNumericRange.spec.ts
index 805df9df..d68cb3bf 100644
--- a/test/unit/arbitrary/_internals/helpers/BiasNumericRange.spec.ts
+++ b/test/unit/arbitrary/_internals/helpers/BiasNumericRange.spec.ts
@@ -8,26 +8,30 @@ import {
 describe('biasNumericRange', () => {
   it('should bias close to extreme values and zero if min and max have opposite signs', () =>
     fc.assert(
-      fc.property(fc.integer(Number.MIN_SAFE_INTEGER, -1), fc.integer(1, Number.MAX_SAFE_INTEGER), (min, max) => {
-        // Arrange / Act
-        const ranges = biasNumericRange(min, max, integerLogLike);
+      fc.property(
+        fc.integer({ min: Number.MIN_SAFE_INTEGER, max: -1 }),
+        fc.integer({ min: 1, max: Number.MAX_SAFE_INTEGER }),
+        (min, max) => {
+          // Arrange / Act
+          const ranges = biasNumericRange(min, max, integerLogLike);
 
-        // Assert
-        expect(ranges).toHaveLength(3);
-        expect(ranges).toEqual([
-          { min: expect.toBeWithinRange(min, 0), max: expect.toBeWithinRange(0, max) }, // close to zero
-          { min: expect.toBeWithinRange(0, max), max: max }, // close to max
-          { min: min, max: expect.toBeWithinRange(min, 0) }, // close to min
-        ]);
-      })
+          // Assert
+          expect(ranges).toHaveLength(3);
+          expect(ranges).toEqual([
+            { min: expect.toBeWithinRange(min, 0), max: expect.toBeWithinRange(0, max) }, // close to zero
+            { min: expect.toBeWithinRange(0, max), max: max }, // close to max
+            { min: min, max: expect.toBeWithinRange(min, 0) }, // close to min
+          ]);
+        }
+      )
     ));
 
   it('should bias close to extreme values if min and max have same signs', () =>
     fc.assert(
       fc.property(
         fc.constantFrom(1, -1),
-        fc.integer(0, Number.MAX_SAFE_INTEGER),
-        fc.integer(0, Number.MAX_SAFE_INTEGER),
+        fc.integer({ min: 0, max: Number.MAX_SAFE_INTEGER }),
+        fc.integer({ min: 0, max: Number.MAX_SAFE_INTEGER }),
         (sign, minRaw, maxRaw) => {
           // Arrange
           fc.pre(minRaw !== maxRaw);
diff --git a/test/unit/arbitrary/_internals/helpers/FloatHelpers.spec.ts b/test/unit/arbitrary/_internals/helpers/FloatHelpers.spec.ts
index e5e408d4..cbf29526 100644
--- a/test/unit/arbitrary/_internals/helpers/FloatHelpers.spec.ts
+++ b/test/unit/arbitrary/_internals/helpers/FloatHelpers.spec.ts
@@ -149,7 +149,7 @@ describe('indexToFloat', () => {
 
   it('should only produce 32-bit floating point numbers (excluding NaN)', () => {
     fc.assert(
-      fc.property(fc.integer(-2139095041, 2139095040), (index) => {
+      fc.property(fc.integer({ min: -2139095041, max: 2139095040 }), (index) => {
         // Arrange / Act
         const f = indexToFloat(index);
 
@@ -173,7 +173,7 @@ describe('indexToFloat', () => {
 
   it('should be reversed by floatToIndex', () => {
     fc.assert(
-      fc.property(fc.integer(-2139095041, 2139095040), (index) => {
+      fc.property(fc.integer({ min: -2139095041, max: 2139095040 }), (index) => {
         // The test below checks that indexToFloat(floatToIndex) is identity
         // It does not confirm that floatToIndex(indexToFloat)) is identity
         expect(floatToIndex(indexToFloat(index))).toBe(index);
diff --git a/test/unit/arbitrary/_internals/helpers/ToggleFlags.spec.ts b/test/unit/arbitrary/_internals/helpers/ToggleFlags.spec.ts
index 0a3aabbe..cdd9ca34 100644
--- a/test/unit/arbitrary/_internals/helpers/ToggleFlags.spec.ts
+++ b/test/unit/arbitrary/_internals/helpers/ToggleFlags.spec.ts
@@ -76,7 +76,7 @@ describe('computeNextFlags', () => {
 
   it('should preserve the position of existing flags', () => {
     fc.assert(
-      fc.property(fc.bigUint(), fc.integer(1, 100), (flags, nextSize) => {
+      fc.property(fc.bigUint(), fc.integer({ min: 1, max: 100 }), (flags, nextSize) => {
         const nextFlags = computeNextFlags(flags, nextSize);
         for (let idx = 0, mask = BigInt(1); idx !== nextSize; ++idx, mask <<= BigInt(1)) {
           if (flags & mask) expect(!!(nextFlags & mask)).toBe(true);
diff --git a/test/unit/arbitrary/date.spec.ts b/test/unit/arbitrary/date.spec.ts
index ec35f000..0b694829 100644
--- a/test/unit/arbitrary/date.spec.ts
+++ b/test/unit/arbitrary/date.spec.ts
@@ -12,7 +12,8 @@ import {
 
 import * as _IntegerMock from '../../../src/arbitrary/integer';
 import { ArbitraryWithShrink } from '../../../src/check/arbitrary/definition/ArbitraryWithShrink';
-const IntegerMock: { integer: (min: number, max: number) => ArbitraryWithShrink<number> } = _IntegerMock;
+const IntegerMock: { integer: (constraints?: _IntegerMock.IntegerConstraints) => ArbitraryWithShrink<number> } =
+  _IntegerMock;
 
 function beforeEachHook() {
   jest.resetModules();
@@ -55,9 +56,9 @@ describe('date', () => {
 
         // Act
         date(constraints);
-        const [rangeMin] = integer.mock.calls[0];
+        const { min: rangeMin } = integer.mock.calls[0][0]!;
         const [mapper] = map.mock.calls[0];
-        const minDate = mapper(rangeMin) as Date;
+        const minDate = mapper(rangeMin!) as Date;
 
         // Assert
         if (constraints.min !== undefined) {
@@ -85,9 +86,9 @@ describe('date', () => {
 
         // Act
         date(constraints);
-        const [, rangeMax] = integer.mock.calls[0];
+        const { max: rangeMax } = integer.mock.calls[0][0]!;
         const [mapper] = map.mock.calls[0];
-        const maxDate = mapper(rangeMax) as Date;
+        const maxDate = mapper(rangeMax!) as Date;
 
         // Assert
         if (constraints.max !== undefined) {
@@ -115,9 +116,9 @@ describe('date', () => {
 
         // Act
         date(constraints);
-        const [rangeMin, rangeMax] = integer.mock.calls[0];
+        const { min: rangeMin, max: rangeMax } = integer.mock.calls[0][0]!;
         const [mapper] = map.mock.calls[0];
-        const d = mapper(rangeMin + (mod % (rangeMax - rangeMin + 1))) as Date;
+        const d = mapper(rangeMin! + (mod % (rangeMax! - rangeMin! + 1))) as Date;
 
         // Assert
         expect(d.getTime()).not.toBe(Number.NaN);
diff --git a/test/unit/check/runner/Runner.spec.ts b/test/unit/check/runner/Runner.spec.ts
index 9666c0d5..06276524 100644
--- a/test/unit/check/runner/Runner.spec.ts
+++ b/test/unit/check/runner/Runner.spec.ts
@@ -229,7 +229,7 @@ describe('Runner', () => {
     });
     it('Should call the property 100 times by default (except on error)', () =>
       fc.assert(
-        fc.property(fc.integer(1, 100), fc.integer(), (num, seed) => {
+        fc.property(fc.integer({ min: 1, max: 100 }), fc.integer(), (num, seed) => {
           let numCallsGenerate = 0;
           let numCallsRun = 0;
           const p: IRawProperty<[number]> = {
@@ -394,7 +394,7 @@ describe('Runner', () => {
       ));
     it('Should wait on async properties to complete', async () =>
       fc.assert(
-        fc.asyncProperty(fc.integer(1, 100), fc.integer(), async (num, seed) => {
+        fc.asyncProperty(fc.integer({ min: 1, max: 100 }), fc.integer(), async (num, seed) => {
           const delay = () => new Promise((resolve) => setTimeout(resolve, 0));
 
           let runnerHasCompleted = false;
diff --git a/test/unit/check/runner/Sampler.spec.ts b/test/unit/check/runner/Sampler.spec.ts
index 44737f7f..b89ca312 100644
--- a/test/unit/check/runner/Sampler.spec.ts
+++ b/test/unit/check/runner/Sampler.spec.ts
@@ -81,7 +81,7 @@ describe('Sampler', () => {
     const rePercent = /(\d+\.\d+)%$/;
     it('Should always produce for non null number of runs', () =>
       fc.assert(
-        fc.property(fc.integer(), fc.integer(1, MAX_NUM_RUNS), (seed, runs) => {
+        fc.property(fc.integer(), fc.integer({ min: 1, max: MAX_NUM_RUNS }), (seed, runs) => {
           const logs: string[] = [];
           const classify = (g: number) => g.toString();
           statistics(customGen(), classify, { seed: seed, numRuns: runs, logger: (v: string) => logs.push(v) });
@@ -170,7 +170,7 @@ describe('Sampler', () => {
       ));
     it('Should not produce more logs than the number of classified values', () =>
       fc.assert(
-        fc.property(fc.integer(), fc.integer(1, 100), (seed, mod) => {
+        fc.property(fc.integer(), fc.integer({ min: 1, max: 100 }), (seed, mod) => {
           const logs: string[] = [];
           const classify = (g: number) => g.toString();
           statistics(customGen(mod), classify, { seed: seed, logger: (v: string) => logs.push(v) });
diff --git a/test/unit/check/runner/SourceValuesIterator.spec.ts b/test/unit/check/runner/SourceValuesIterator.spec.ts
index b6cb2135..552985b3 100644
--- a/test/unit/check/runner/SourceValuesIterator.spec.ts
+++ b/test/unit/check/runner/SourceValuesIterator.spec.ts
@@ -116,7 +116,7 @@ describe('SourceValuesIterator', () => {
       fc.assert(
         fc.property(
           fc.uniqueArray(fc.nat(100), { minLength: 1, maxLength: 20 }),
-          fc.integer(1, 100),
+          fc.integer({ min: 1, max: 100 }),
           (skippedValues, missingValues) => {
             const lastSkip = skippedValues.reduce((prev, cur) => (prev > cur ? prev : cur), 0);
             const askedValues = lastSkip + 1 - skippedValues.length + missingValues;
diff --git a/test/unit/check/runner/configuration/QualifiedParameters.spec.ts b/test/unit/check/runner/configuration/QualifiedParameters.spec.ts
index 284cdaa4..36dbaaa7 100644
--- a/test/unit/check/runner/configuration/QualifiedParameters.spec.ts
+++ b/test/unit/check/runner/configuration/QualifiedParameters.spec.ts
@@ -80,7 +80,7 @@ describe('QualifiedParameters', () => {
       const seedsOutsideRangeArb = fc.oneof(
         fc.double(),
         fc.double({ min: Number.MIN_VALUE, max: Number.MAX_VALUE }),
-        fc.integer(Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER),
+        fc.integer({ min: Number.MIN_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER }),
         fc.constantFrom(Number.POSITIVE_INFINITY, Number.NEGATIVE_INFINITY, Number.NaN)
       );
       it('Should produce 32 bits signed seed', () =>
@@ -109,7 +109,7 @@ describe('QualifiedParameters', () => {
         ));
       it('Should truncate integer values into a 32 signed bits seed', () =>
         fc.assert(
-          fc.property(fc.integer(Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER), (unsafeSeed) => {
+          fc.property(fc.integer({ min: Number.MIN_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER }), (unsafeSeed) => {
             const qparams = QualifiedParameters.read({ seed: unsafeSeed });
             return qparams.seed === (unsafeSeed | 0);
           })
diff --git a/test/unit/utils/stringify.spec.ts b/test/unit/utils/stringify.spec.ts
index 80739955..2b1dda82 100644
--- a/test/unit/utils/stringify.spec.ts
+++ b/test/unit/utils/stringify.spec.ts
@@ -322,31 +322,34 @@ describe('stringify', () => {
   });
   it('Should be able to stringify Int8Array', () => {
     expect(stringify(Int8Array.from([-128, 5, 127]))).toEqual('Int8Array.from([-128,5,127])');
-    assertStringifyTypedArraysProperly(fc.integer(-128, 127), Int8Array.from.bind(Int8Array));
+    assertStringifyTypedArraysProperly(fc.integer({ min: -128, max: 127 }), Int8Array.from.bind(Int8Array));
   });
   it('Should be able to stringify Uint8Array', () => {
     expect(stringify(Uint8Array.from([255, 0, 5, 127]))).toEqual('Uint8Array.from([255,0,5,127])');
-    assertStringifyTypedArraysProperly(fc.integer(0, 255), Uint8Array.from.bind(Uint8Array));
+    assertStringifyTypedArraysProperly(fc.integer({ min: 0, max: 255 }), Uint8Array.from.bind(Uint8Array));
   });
   it('Should be able to stringify Int16Array', () => {
     expect(stringify(Int16Array.from([-32768, 5, 32767]))).toEqual('Int16Array.from([-32768,5,32767])');
-    assertStringifyTypedArraysProperly(fc.integer(-32768, 32767), Int16Array.from.bind(Int16Array));
+    assertStringifyTypedArraysProperly(fc.integer({ min: -32768, max: 32767 }), Int16Array.from.bind(Int16Array));
   });
   it('Should be able to stringify Uint16Array', () => {
     expect(stringify(Uint16Array.from([65535, 0, 5, 32767]))).toEqual('Uint16Array.from([65535,0,5,32767])');
-    assertStringifyTypedArraysProperly(fc.integer(0, 65535), Uint16Array.from.bind(Uint16Array));
+    assertStringifyTypedArraysProperly(fc.integer({ min: 0, max: 65535 }), Uint16Array.from.bind(Uint16Array));
   });
   it('Should be able to stringify Int32Array', () => {
     expect(stringify(Int32Array.from([-2147483648, 5, 2147483647]))).toEqual(
       'Int32Array.from([-2147483648,5,2147483647])'
     );
-    assertStringifyTypedArraysProperly(fc.integer(-2147483648, 2147483647), Int32Array.from.bind(Int32Array));
+    assertStringifyTypedArraysProperly(
+      fc.integer({ min: -2147483648, max: 2147483647 }),
+      Int32Array.from.bind(Int32Array)
+    );
   });
   it('Should be able to stringify Uint32Array', () => {
     expect(stringify(Uint32Array.from([4294967295, 0, 5, 2147483647]))).toEqual(
       'Uint32Array.from([4294967295,0,5,2147483647])'
     );
-    assertStringifyTypedArraysProperly(fc.integer(0, 4294967295), Uint32Array.from.bind(Uint32Array));
+    assertStringifyTypedArraysProperly(fc.integer({ min: 0, max: 4294967295 }), Uint32Array.from.bind(Uint32Array));
   });
   it('Should be able to stringify Float32Array', () => {
     expect(stringify(Float32Array.from([0, 0.5, 30, -1]))).toEqual('Float32Array.from([0,0.5,30,-1])');