Repository: marpple/FxTS
Pull request #314 (2025-04-02 13:24:26)

feat: add `zip` to `fx`
add `zip` function to `fx`



Patch:
diff --git a/src/Lazy/fx.ts b/src/Lazy/fx.ts
index ebe4e532..c423c571 100644
--- a/src/Lazy/fx.ts
+++ b/src/Lazy/fx.ts
@@ -29,6 +29,7 @@ import take from "./take";
 import takeUntilInclusive from "./takeUntilInclusive";
 import takeWhile from "./takeWhile";
 import toAsync from "./toAsync";
+import zip from "./zip";
 
 class FxAsyncIterable<A> {
   private asyncIterable: AsyncIterable<A>;
@@ -219,6 +220,17 @@ class FxAsyncIterable<A> {
     return new FxAsyncIterable(chunk(size, this.asyncIterable));
   }
 
+  /**
+   * Merges the values of each of the arrays with the values at the corresponding position together.
+   * Useful when you have separate data sources that are coordinated through matching array indices.
+   * It works the same way as `zip`.
+   *
+   * see {@link https://fxts.dev/docs/zip | zip}
+   */
+  zip<B>(iterable: Iterable<B> | AsyncIterable<B>): FxAsyncIterable<[A, B]> {
+    return new FxAsyncIterable(zip(this.asyncIterable, iterable));
+  }
+
   /**
    * Concurrent is used to balance the load of multiple asynchronous requests.
    * The first argument receives a number that controls the number of loads, and the second argument is an AsyncIterable.
@@ -532,6 +544,17 @@ export class FxIterable<A> {
     return new FxIterable(chunk(size, this.iterable));
   }
 
+  /**
+   * Merges the values of each of the arrays with the values at the corresponding position together.
+   * Useful when you have separate data sources that are coordinated through matching array indices.
+   * It works the same way as `zip`.
+   *
+   * see {@link https://fxts.dev/docs/zip | zip}
+   */
+  zip<B>(iterable: Iterable<B>): FxIterable<[A, B]> {
+    return new FxIterable(zip(this.iterable, iterable));
+  }
+
   /**
    * Returns AsyncIterable, `toAsync` used when you want to handle Promise values inside Iterable.
    *


Test patch:
diff --git a/test/Lazy/zip.spec.ts b/test/Lazy/zip.spec.ts
index 7d23a46a..5d653142 100644
--- a/test/Lazy/zip.spec.ts
+++ b/test/Lazy/zip.spec.ts
@@ -1,6 +1,7 @@
 import {
   concurrent,
   delay,
+  fx,
   map,
   pipe,
   toArray,
@@ -94,6 +95,24 @@ describe("zip", function () {
         [4, 8],
       ]);
     });
+
+    it("should be able to be used as a chaining method in the `fx`", function () {
+      const res1 = fx([1, 2, 3]).zip(["5", "6", "7", "8"]).toArray();
+
+      expect(res1).toEqual([
+        [1, "5"],
+        [2, "6"],
+        [3, "7"],
+      ]);
+
+      const res2 = fx([1, 2, 3, 4]).zip(["5", "6", "7"]).toArray();
+
+      expect(res2).toEqual([
+        [1, "5"],
+        [2, "6"],
+        [3, "7"],
+      ]);
+    });
   });
 
   const sum = (a: number, b: number) => a + b;
@@ -176,6 +195,30 @@ describe("zip", function () {
       expect(res).toEqual([[6], [8], [10], [12]]);
     });
 
+    it("should be able to be used as a chaining method in the `fx`", async function () {
+      const res1 = await fx([1, 2, 3])
+        .toAsync()
+        .zip(["5", "6", "7", "8"])
+        .toArray();
+
+      expect(res1).toEqual([
+        [1, "5"],
+        [2, "6"],
+        [3, "7"],
+      ]);
+
+      const res2 = await fx([1, 2, 3, 4])
+        .toAsync()
+        .zip(["5", "6", "7"])
+        .toArray();
+
+      expect(res2).toEqual([
+        [1, "5"],
+        [2, "6"],
+        [3, "7"],
+      ]);
+    });
+
     it("should be zipped each 'AsyncIterable' having a different type", async function () {
       const res = await pipe(
         ["a", "b", "c", "d"],
diff --git a/type-check/Lazy/zip.test.ts b/type-check/Lazy/zip.test.ts
index 89ae3529..ad7d7663 100644
--- a/type-check/Lazy/zip.test.ts
+++ b/type-check/Lazy/zip.test.ts
@@ -1,4 +1,4 @@
-import { pipe, toAsync, zip } from "../../src";
+import { fx, pipe, toAsync, zip } from "../../src";
 import * as Test from "../../src/types/Test";
 
 const { checks, check } = Test;
@@ -10,6 +10,8 @@ const res3 = zip([1, 2, 3], toAsync("abc"), [true, false, true]);
 const res4 = pipe([1, 2, 3], zip("abc"));
 const res5 = pipe([1, 2, 3], toAsync, zip("abc"));
 const res6 = pipe([1, 2, 3], zip(toAsync("abc")));
+const res7 = fx([1, 2, 3]).zip(["a", "b", "c"]).toArray();
+const res8 = fx([1, 2, 3]).toAsync().zip(["a", "b", "c"]).toArray();
 
 checks([
   check<typeof res1, IterableIterator<[number, string, boolean]>, Test.Pass>(),
@@ -22,4 +24,6 @@ checks([
   check<typeof res4, IterableIterator<[string, number]>, Test.Pass>(),
   check<typeof res5, AsyncIterableIterator<[string, number]>, Test.Pass>(),
   check<typeof res6, AsyncIterableIterator<[string, number]>, Test.Pass>(),
+  check<typeof res7, [number, string][], Test.Pass>(),
+  check<typeof res8, Promise<[number, string][]>, Test.Pass>(),
 ]);