Repository: dubzzz/fast-check
Pull request #2156 (2021-08-01 22:02:40)

⬆️ Bump @types/lodash from 4.14.170 to 4.14.171 in /example
Bumps [@types/lodash](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/lodash) from 4.14.170 to 4.14.171.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a href="https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/lodash">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@types/lodash&package-manager=npm_and_yarn&previous-version=4.14.170&new-version=4.14.171)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>

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/2156/builds/155248) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 22e8a4f04a46914fb66092a5a05ffd7502b490ff:

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

codecov[bot]: # [Codecov](https://codecov.io/gh/dubzzz/fast-check/pull/2156?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN) Report
> Merging [#2156](https://codecov.io/gh/dubzzz/fast-check/pull/2156?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN) (22e8a4f) into [main](https://codecov.io/gh/dubzzz/fast-check/commit/1d0684078a3b0fce8d96da93747e9d07ff24bb12?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN) (1d06840) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/dubzzz/fast-check/pull/2156/graphs/tree.svg?width=650&height=150&src=pr&token=fRi2fJN730&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN)](https://codecov.io/gh/dubzzz/fast-check/pull/2156?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN)

```diff
@@           Coverage Diff           @@
##             main    #2156   +/-   ##
=======================================
  Coverage   96.41%   96.41%           
=======================================
  Files         197      197           
  Lines        4519     4519           
  Branches      887      887           
=======================================
  Hits         4357     4357           
  Misses        158      158           
  Partials        4        4           
```

| Flag | Coverage Δ | |
|---|---|---|
| unit-tests | `96.41% <ø> (ø)` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN#carryforward-flags-in-the-pull-request-comment) to find out more.


------

[Continue to review full report at Codecov](https://codecov.io/gh/dubzzz/fast-check/pull/2156?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/dubzzz/fast-check/pull/2156?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN). Last update [1d06840...22e8a4f](https://codecov.io/gh/dubzzz/fast-check/pull/2156?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN).


Patch:
diff --git a/example/package.json b/example/package.json
index 9931909c..bc2fdc40 100644
--- a/example/package.json
+++ b/example/package.json
@@ -18,7 +18,7 @@
   },
   "devDependencies": {
     "@types/jest": "^26.0.23",
-    "@types/lodash": "^4.14.170",
+    "@types/lodash": "^4.14.171",
     "@types/react": "^17.0.13",
     "jest": "^26.6.3",
     "ts-jest": "^26.5.6",
diff --git a/example/yarn.lock b/example/yarn.lock
index a6b234a5..32d7712b 100644
--- a/example/yarn.lock
+++ b/example/yarn.lock
@@ -621,10 +621,10 @@
     jest-diff "^26.0.0"
     pretty-format "^26.0.0"
 
-"@types/lodash@^4.14.170":
-  version "4.14.170"
-  resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.170.tgz#0d67711d4bf7f4ca5147e9091b847479b87925d6"
-  integrity sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q==
+"@types/lodash@^4.14.171":
+  version "4.14.171"
+  resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.171.tgz#f01b3a5fe3499e34b622c362a46a609fdb23573b"
+  integrity sha512-7eQ2xYLLI/LsicL2nejW9Wyko3lcpN6O/z0ZLHrEQsg280zIdCv1t/0m6UtBjUHokCGBQ3gYTbHzDkZ1xOBwwg==
 
 "@types/node@*":
   version "14.14.20"
diff --git a/package.json b/package.json
index 501d577c..a4176814 100644
--- a/package.json
+++ b/package.json
@@ -32,6 +32,7 @@
     "watch": "tsc -w",
     "test": "jest --config jest.unit.config.cjs --coverage",
     "test:watch": "jest --config jest.unit.config.cjs --watch",
+    "test:debug": "node --inspect node_modules/jest/bin/jest.js --config jest.unit.config.cjs --watch --runInBand",
     "e2e": "jest --config jest.e2e.config.cjs --coverage",
     "e2e:watch": "jest --config jest.e2e.config.cjs --watch",
     "update:examples": "cross-env UPDATE_CODE_SNIPPETS=true jest --config jest.examples.config.cjs",
diff --git a/src/arbitrary/_internals/SubarrayArbitrary.ts b/src/arbitrary/_internals/SubarrayArbitrary.ts
new file mode 100644
index 00000000..6edeccac
--- /dev/null
+++ b/src/arbitrary/_internals/SubarrayArbitrary.ts
@@ -0,0 +1,95 @@
+import { NextArbitrary } from '../../check/arbitrary/definition/NextArbitrary';
+import { NextValue } from '../../check/arbitrary/definition/NextValue';
+import { Random } from '../../random/generator/Random';
+import { makeLazy } from '../../stream/LazyIterableIterator';
+import { Stream } from '../../stream/Stream';
+import { isSubarrayOf } from './helpers/IsSubarrayOf';
+import { IntegerArbitrary } from './IntegerArbitrary';
+
+/** @internal */
+export class SubarrayArbitrary<T> extends NextArbitrary<T[]> {
+  readonly lengthArb: NextArbitrary<number>;
+  readonly biasedLengthArb: NextArbitrary<number>;
+  constructor(
+    readonly originalArray: T[],
+    readonly isOrdered: boolean,
+    readonly minLength: number,
+    readonly maxLength: number
+  ) {
+    super();
+    if (minLength < 0 || minLength > originalArray.length)
+      throw new Error(
+        'fc.*{s|S}ubarrayOf expects the minimal length to be between 0 and the size of the original array'
+      );
+    if (maxLength < 0 || maxLength > originalArray.length)
+      throw new Error(
+        'fc.*{s|S}ubarrayOf expects the maximal length to be between 0 and the size of the original array'
+      );
+    if (minLength > maxLength)
+      throw new Error('fc.*{s|S}ubarrayOf expects the minimal length to be inferior or equal to the maximal length');
+
+    this.lengthArb = new IntegerArbitrary(minLength, maxLength);
+    this.biasedLengthArb =
+      minLength !== maxLength
+        ? new IntegerArbitrary(minLength, minLength + Math.floor(Math.log(maxLength - minLength) / Math.log(2)))
+        : this.lengthArb;
+  }
+
+  generate(mrng: Random, biasFactor: number | undefined): NextValue<T[]> {
+    const lengthArb =
+      biasFactor !== undefined && mrng.nextInt(1, biasFactor) === 1 ? this.biasedLengthArb : this.lengthArb;
+    const size = lengthArb.generate(mrng, undefined);
+    const sizeValue = size.value;
+
+    const remainingElements = this.originalArray.map((_v, idx) => idx);
+    const ids: number[] = [];
+    for (let index = 0; index !== sizeValue; ++index) {
+      const selectedIdIndex = mrng.nextInt(0, remainingElements.length - 1);
+      ids.push(remainingElements[selectedIdIndex]);
+      remainingElements.splice(selectedIdIndex, 1);
+    }
+    if (this.isOrdered) {
+      ids.sort((a, b) => a - b);
+    }
+
+    return new NextValue(
+      ids.map((i) => this.originalArray[i]),
+      size.context
+    );
+  }
+
+  canShrinkWithoutContext(value: unknown): value is T[] {
+    if (!Array.isArray(value)) {
+      return false;
+    }
+    if (!this.lengthArb.canShrinkWithoutContext(value.length)) {
+      return false;
+    }
+    return isSubarrayOf(this.originalArray, value);
+  }
+
+  shrink(value: T[], context: unknown): Stream<NextValue<T[]>> {
+    // shrinking one by one is not the most comprehensive
+    // but allows a reasonable number of entries in the shrink
+    if (value.length === 0) {
+      return Stream.nil<NextValue<T[]>>();
+    }
+    return this.lengthArb
+      .shrink(value.length, context)
+      .map((newSize) => {
+        return new NextValue(
+          value.slice(value.length - newSize.value), // array of length newSize.value
+          newSize.context // integer context for value newSize.value (the length)
+        );
+      })
+      .join(
+        value.length > this.minLength
+          ? makeLazy(() =>
+              this.shrink(value.slice(1), undefined)
+                .filter((newValue) => this.minLength <= newValue.value.length + 1)
+                .map((newValue) => new NextValue([value[0]].concat(newValue.value), undefined))
+            )
+          : Stream.nil<NextValue<T[]>>()
+      );
+  }
+}
diff --git a/src/arbitrary/_internals/helpers/IsSubarrayOf.ts b/src/arbitrary/_internals/helpers/IsSubarrayOf.ts
new file mode 100644
index 00000000..852681f0
--- /dev/null
+++ b/src/arbitrary/_internals/helpers/IsSubarrayOf.ts
@@ -0,0 +1,27 @@
+export function isSubarrayOf(source: unknown[], small: unknown[]): boolean {
+  const countMap = new Map<unknown, number>();
+  let countMinusZero = 0;
+  for (const sourceEntry of source) {
+    if (Object.is(sourceEntry, -0)) {
+      ++countMinusZero;
+    } else {
+      const oldCount = countMap.get(sourceEntry) || 0;
+      countMap.set(sourceEntry, oldCount + 1);
+    }
+  }
+  for (let index = 0; index !== small.length; ++index) {
+    if (!(index in small)) {
+      return false;
+    }
+    const smallEntry = small[index];
+    if (Object.is(smallEntry, -0)) {
+      if (countMinusZero === 0) return false;
+      --countMinusZero;
+    } else {
+      const oldCount = countMap.get(smallEntry) || 0;
+      if (oldCount === 0) return false;
+      countMap.set(smallEntry, oldCount - 1);
+    }
+  }
+  return true;
+}
diff --git a/src/arbitrary/shuffledSubarray.ts b/src/arbitrary/shuffledSubarray.ts
new file mode 100644
index 00000000..faf6ce88
--- /dev/null
+++ b/src/arbitrary/shuffledSubarray.ts
@@ -0,0 +1,71 @@
+import { Arbitrary } from '../check/arbitrary/definition/Arbitrary';
+import { convertFromNext } from '../check/arbitrary/definition/Converters';
+import { SubarrayArbitrary } from './_internals/SubarrayArbitrary';
+
+/**
+ * Constraints to be applied on {@link shuffledSubarray}
+ * @remarks Since 2.18.0
+ * @public
+ */
+export interface ShuffledSubarrayConstraints {
+  /**
+   * Lower bound of the generated subarray size (included)
+   * @defaultValue 0
+   * @remarks Since 2.4.0
+   */
+  minLength?: number;
+  /**
+   * Upper bound of the generated subarray size (included)
+   * @defaultValue The length of the original array itself
+   * @remarks Since 2.4.0
+   */
+  maxLength?: number;
+}
+
+/**
+ * For subarrays of `originalArray`
+ *
+ * @param originalArray - Original array
+ *
+ * @remarks Since 1.5.0
+ * @public
+ */
+function shuffledSubarray<T>(originalArray: T[]): Arbitrary<T[]>;
+/**
+ * For subarrays of `originalArray`
+ *
+ * @param originalArray - Original array
+ * @param minLength - Lower bound of the generated array size
+ * @param maxLength - Upper bound of the generated array size
+ *
+ * @deprecated
+ * Superceded by `fc.shuffledSubarray(originalArray, {minLength, maxLength})` - see {@link https://github.com/dubzzz/fast-check/issues/992 | #992}.
+ * Ease the migration with {@link https://github.com/dubzzz/fast-check/tree/main/codemods/unify-signatures | our codemod script}.
+ *
+ * @remarks Since 1.5.0
+ * @public
+ */
+function shuffledSubarray<T>(originalArray: T[], minLength: number, maxLength: number): Arbitrary<T[]>;
+/**
+ * For subarrays of `originalArray`
+ *
+ * @param originalArray - Original array
+ * @param constraints - Constraints to apply when building instances
+ *
+ * @remarks Since 2.4.0
+ * @public
+ */
+function shuffledSubarray<T>(originalArray: T[], constraints: ShuffledSubarrayConstraints): Arbitrary<T[]>;
+function shuffledSubarray<T>(
+  originalArray: T[],
+  ...args: [] | [number, number] | [ShuffledSubarrayConstraints]
+): Arbitrary<T[]> {
+  if (typeof args[0] === 'number' && typeof args[1] === 'number') {
+    return convertFromNext(new SubarrayArbitrary(originalArray, false, args[0], args[1]));
+  }
+  const ct = args[0] as ShuffledSubarrayConstraints | undefined;
+  const minLength = ct !== undefined && ct.minLength !== undefined ? ct.minLength : 0;
+  const maxLength = ct !== undefined && ct.maxLength !== undefined ? ct.maxLength : originalArray.length;
+  return convertFromNext(new SubarrayArbitrary(originalArray, false, minLength, maxLength));
+}
+export { shuffledSubarray };
diff --git a/src/arbitrary/subarray.ts b/src/arbitrary/subarray.ts
new file mode 100644
index 00000000..cf9f80b6
--- /dev/null
+++ b/src/arbitrary/subarray.ts
@@ -0,0 +1,68 @@
+import { Arbitrary } from '../check/arbitrary/definition/Arbitrary';
+import { convertFromNext } from '../check/arbitrary/definition/Converters';
+import { SubarrayArbitrary } from './_internals/SubarrayArbitrary';
+
+/**
+ * Constraints to be applied on {@link subarray}
+ * @remarks Since 2.4.0
+ * @public
+ */
+export interface SubarrayConstraints {
+  /**
+   * Lower bound of the generated subarray size (included)
+   * @defaultValue 0
+   * @remarks Since 2.4.0
+   */
+  minLength?: number;
+  /**
+   * Upper bound of the generated subarray size (included)
+   * @defaultValue The length of the original array itself
+   * @remarks Since 2.4.0
+   */
+  maxLength?: number;
+}
+
+/**
+ * For subarrays of `originalArray` (keeps ordering)
+ *
+ * @param originalArray - Original array
+ *
+ * @remarks Since 1.5.0
+ * @public
+ */
+function subarray<T>(originalArray: T[]): Arbitrary<T[]>;
+/**
+ * For subarrays of `originalArray` (keeps ordering)
+ *
+ * @param originalArray - Original array
+ * @param minLength - Lower bound of the generated array size
+ * @param maxLength - Upper bound of the generated array size
+ *
+ * @deprecated
+ * Superceded by `fc.subarray(originalArray, {minLength, maxLength})` - see {@link https://github.com/dubzzz/fast-check/issues/992 | #992}.
+ * Ease the migration with {@link https://github.com/dubzzz/fast-check/tree/main/codemods/unify-signatures | our codemod script}.
+ *
+ * @remarks Since 1.5.0
+ * @public
+ */
+function subarray<T>(originalArray: T[], minLength: number, maxLength: number): Arbitrary<T[]>;
+/**
+ * For subarrays of `originalArray` (keeps ordering)
+ *
+ * @param originalArray - Original array
+ * @param constraints - Constraints to apply when building instances
+ *
+ * @remarks Since 2.4.0
+ * @public
+ */
+function subarray<T>(originalArray: T[], constraints: SubarrayConstraints): Arbitrary<T[]>;
+function subarray<T>(originalArray: T[], ...args: [] | [number, number] | [SubarrayConstraints]): Arbitrary<T[]> {
+  if (typeof args[0] === 'number' && typeof args[1] === 'number') {
+    return convertFromNext(new SubarrayArbitrary(originalArray, true, args[0], args[1]));
+  }
+  const ct = args[0] as SubarrayConstraints | undefined;
+  const minLength = ct !== undefined && ct.minLength !== undefined ? ct.minLength : 0;
+  const maxLength = ct !== undefined && ct.maxLength !== undefined ? ct.maxLength : originalArray.length;
+  return convertFromNext(new SubarrayArbitrary(originalArray, true, minLength, maxLength));
+}
+export { subarray };
diff --git a/src/check/arbitrary/SubarrayArbitrary.ts b/src/check/arbitrary/SubarrayArbitrary.ts
deleted file mode 100644
index a0a6560e..00000000
--- a/src/check/arbitrary/SubarrayArbitrary.ts
+++ /dev/null
@@ -1,204 +0,0 @@
-import { Random } from '../../random/generator/Random';
-import { Stream } from '../../stream/Stream';
-import { Arbitrary } from './definition/Arbitrary';
-import { ArbitraryWithContextualShrink } from './definition/ArbitraryWithContextualShrink';
-import { biasWrapper } from './definition/BiasedArbitraryWrapper';
-import { Shrinkable } from './definition/Shrinkable';
-import { integer } from '../../arbitrary/integer';
-import { makeLazy } from '../../stream/LazyIterableIterator';
-
-/** @internal */
-class SubarrayArbitrary<T> extends Arbitrary<T[]> {
-  readonly lengthArb: ArbitraryWithContextualShrink<number>;
-  constructor(
-    readonly originalArray: T[],
-    readonly isOrdered: boolean,
-    readonly minLength: number,
-    readonly maxLength: number
-  ) {
-    super();
-    if (minLength < 0 || minLength > originalArray.length)
-      throw new Error(
-        'fc.*{s|S}ubarrayOf expects the minimal length to be between 0 and the size of the original array'
-      );
-    if (maxLength < 0 || maxLength > originalArray.length)
-      throw new Error(
-        'fc.*{s|S}ubarrayOf expects the maximal length to be between 0 and the size of the original array'
-      );
-    if (minLength > maxLength)
-      throw new Error('fc.*{s|S}ubarrayOf expects the minimal length to be inferior or equal to the maximal length');
-    this.lengthArb = integer(minLength, maxLength);
-  }
-  private wrapper(items: T[], itemsLengthContext: unknown): Shrinkable<T[]> {
-    return new Shrinkable(items, () =>
-      this.shrinkImpl(items, itemsLengthContext).map((contextualValue) =>
-        this.wrapper(contextualValue[0], contextualValue[1])
-      )
-    );
-  }
-  generate(mrng: Random): Shrinkable<T[]> {
-    const remainingElements = this.originalArray.map((_v, idx) => idx);
-    const size = this.lengthArb.generate(mrng).value;
-    const ids: number[] = [];
-    for (let idx = 0; idx !== size; ++idx) {
-      const selectedIdIndex = mrng.nextInt(0, remainingElements.length - 1);
-      ids.push(remainingElements[selectedIdIndex]);
-      remainingElements.splice(selectedIdIndex, 1);
-    }
-    if (this.isOrdered) ids.sort((a, b) => a - b);
-    return this.wrapper(
-      ids.map((i) => this.originalArray[i]),
-      undefined
-    );
-  }
-  private shrinkImpl(items: T[], itemsLengthContext: unknown): Stream<[T[], unknown]> {
-    // shrinking one by one is the not the most comprehensive
-    // but allows a reasonable number of entries in the shrink
-    if (items.length === 0) {
-      return Stream.nil<[T[], unknown]>();
-    }
-    return this.lengthArb
-      .contextualShrink(items.length, itemsLengthContext)
-      .map((contextualValue): [T[], unknown] => {
-        return [
-          items.slice(items.length - contextualValue[0]), // array of length contextualValue[0]
-          contextualValue[1], // integer context for value contextualValue[0] (the length)
-        ];
-      })
-      .join(
-        items.length > this.minLength
-          ? makeLazy(() =>
-              this.shrinkImpl(items.slice(1), undefined)
-                .filter((contextualValue) => this.minLength <= contextualValue[0].length + 1)
-                .map((contextualValue) => [[items[0]].concat(contextualValue[0]), undefined])
-            )
-          : Stream.nil<[T[], unknown]>()
-      );
-  }
-  withBias(freq: number): Arbitrary<T[]> {
-    return this.minLength !== this.maxLength
-      ? biasWrapper(freq, this, (originalArbitrary: SubarrayArbitrary<T>) => {
-          return new SubarrayArbitrary(
-            originalArbitrary.originalArray,
-            originalArbitrary.isOrdered,
-            originalArbitrary.minLength,
-            originalArbitrary.minLength +
-              Math.floor(Math.log(originalArbitrary.maxLength - originalArbitrary.minLength) / Math.log(2))
-          );
-        })
-      : this;
-  }
-}
-
-/**
- * Constraints to be applied on {@link subarray} and {@link shuffledSubarray}
- * @remarks Since 2.4.0
- * @public
- */
-export interface SubarrayConstraints {
-  /**
-   * Lower bound of the generated subarray size (included)
-   * @defaultValue 0
-   * @remarks Since 2.4.0
-   */
-  minLength?: number;
-  /**
-   * Upper bound of the generated subarray size (included)
-   * @defaultValue The length of the original array itself
-   * @remarks Since 2.4.0
-   */
-  maxLength?: number;
-}
-
-/**
- * For subarrays of `originalArray` (keeps ordering)
- *
- * @param originalArray - Original array
- *
- * @remarks Since 1.5.0
- * @public
- */
-function subarray<T>(originalArray: T[]): Arbitrary<T[]>;
-/**
- * For subarrays of `originalArray` (keeps ordering)
- *
- * @param originalArray - Original array
- * @param minLength - Lower bound of the generated array size
- * @param maxLength - Upper bound of the generated array size
- *
- * @deprecated
- * Superceded by `fc.subarray(originalArray, {minLength, maxLength})` - see {@link https://github.com/dubzzz/fast-check/issues/992 | #992}.
- * Ease the migration with {@link https://github.com/dubzzz/fast-check/tree/main/codemods/unify-signatures | our codemod script}.
- *
- * @remarks Since 1.5.0
- * @public
- */
-function subarray<T>(originalArray: T[], minLength: number, maxLength: number): Arbitrary<T[]>;
-/**
- * For subarrays of `originalArray` (keeps ordering)
- *
- * @param originalArray - Original array
- * @param constraints - Constraints to apply when building instances
- *
- * @remarks Since 2.4.0
- * @public
- */
-function subarray<T>(originalArray: T[], constraints: SubarrayConstraints): Arbitrary<T[]>;
-function subarray<T>(originalArray: T[], ...args: [] | [number, number] | [SubarrayConstraints]): Arbitrary<T[]> {
-  if (typeof args[0] === 'number' && typeof args[1] === 'number') {
-    return new SubarrayArbitrary(originalArray, true, args[0], args[1]);
-  }
-  const ct = args[0] as SubarrayConstraints | undefined;
-  const minLength = ct !== undefined && ct.minLength !== undefined ? ct.minLength : 0;
-  const maxLength = ct !== undefined && ct.maxLength !== undefined ? ct.maxLength : originalArray.length;
-  return new SubarrayArbitrary(originalArray, true, minLength, maxLength);
-}
-
-/**
- * For subarrays of `originalArray`
- *
- * @param originalArray - Original array
- *
- * @remarks Since 1.5.0
- * @public
- */
-function shuffledSubarray<T>(originalArray: T[]): Arbitrary<T[]>;
-/**
- * For subarrays of `originalArray`
- *
- * @param originalArray - Original array
- * @param minLength - Lower bound of the generated array size
- * @param maxLength - Upper bound of the generated array size
- *
- * @deprecated
- * Superceded by `fc.shuffledSubarray(originalArray, {minLength, maxLength})` - see {@link https://github.com/dubzzz/fast-check/issues/992 | #992}.
- * Ease the migration with {@link https://github.com/dubzzz/fast-check/tree/main/codemods/unify-signatures | our codemod script}.
- *
- * @remarks Since 1.5.0
- * @public
- */
-function shuffledSubarray<T>(originalArray: T[], minLength: number, maxLength: number): Arbitrary<T[]>;
-/**
- * For subarrays of `originalArray`
- *
- * @param originalArray - Original array
- * @param constraints - Constraints to apply when building instances
- *
- * @remarks Since 2.4.0
- * @public
- */
-function shuffledSubarray<T>(originalArray: T[], constraints: SubarrayConstraints): Arbitrary<T[]>;
-function shuffledSubarray<T>(
-  originalArray: T[],
-  ...args: [] | [number, number] | [SubarrayConstraints]
-): Arbitrary<T[]> {
-  if (typeof args[0] === 'number' && typeof args[1] === 'number') {
-    return new SubarrayArbitrary(originalArray, false, args[0], args[1]);
-  }
-  const ct = args[0] as SubarrayConstraints | undefined;
-  const minLength = ct !== undefined && ct.minLength !== undefined ? ct.minLength : 0;
-  const maxLength = ct !== undefined && ct.maxLength !== undefined ? ct.maxLength : originalArray.length;
-  return new SubarrayArbitrary(originalArray, false, minLength, maxLength);
-}
-
-export { subarray, shuffledSubarray };
diff --git a/src/fast-check-default.ts b/src/fast-check-default.ts
index df2797a0..57d1c0c7 100644
--- a/src/fast-check-default.ts
+++ b/src/fast-check-default.ts
@@ -82,7 +82,8 @@ import { string, StringSharedConstraints } from './arbitrary/string';
 import { string16bits } from './arbitrary/string16bits';
 import { stringOf } from './arbitrary/stringOf';
 import { unicodeString } from './arbitrary/unicodeString';
-import { shuffledSubarray, subarray, SubarrayConstraints } from './check/arbitrary/SubarrayArbitrary';
+import { subarray, SubarrayConstraints } from './arbitrary/subarray';
+import { shuffledSubarray, ShuffledSubarrayConstraints } from './arbitrary/shuffledSubarray';
 import { genericTuple } from './arbitrary/genericTuple';
 import { tuple } from './arbitrary/tuple';
 import { uuid } from './arbitrary/uuid';
@@ -381,6 +382,7 @@ export {
   SparseArrayConstraints,
   StringSharedConstraints,
   SubarrayConstraints,
+  ShuffledSubarrayConstraints,
   WebAuthorityConstraints,
   WebUrlConstraints,
   WeightedArbitrary,


Test patch:
diff --git a/test/unit/check/arbitrary/SubarrayArbitrary.spec.ts b/test/unit/check/arbitrary/SubarrayArbitrary.spec.ts
index 1819c916..ea0026f4 100644
--- a/test/unit/check/arbitrary/SubarrayArbitrary.spec.ts
+++ b/test/unit/check/arbitrary/SubarrayArbitrary.spec.ts
@@ -1,6 +1,7 @@
 import * as fc from '../../../../lib/fast-check';
 
-import { subarray, shuffledSubarray } from '../../../../src/check/arbitrary/SubarrayArbitrary';
+import { subarray } from '../../../../src/arbitrary/subarray';
+import { shuffledSubarray } from '../../../../src/arbitrary/shuffledSubarray';
 
 import { generateOneValue } from './generic/GenerateOneValue';
 import * as genericHelper from './generic/GenericArbitraryHelper';