Repository: marpple/FxTS (ts)

Issue:
Add `repeat` function
# Suggestion

<!--
  Please fill in each section completely. Thank you!
-->

## ⭐ Suggestion

<!-- What would you like to be added? -->

Returns a Iterable/AsyncIterable of size `n` containing  a specified value.


## 💻 Use Cases

<!-- What do you want to use this for? -->


```ts
const iter = repeat(2, 10);
iter.next(); // {value: 10, done:false}
iter.next(); // {value: 10, done:false}
iter.next(); // {value: undefined, done:true}

// with pipe
pipe(
  repeat(2, 10),
  toArray,
); // [10, 10]

```


Pull request description:
feat: add `repeat` function
Fixes #60 


Patch:
diff --git a/src/Lazy/index.ts b/src/Lazy/index.ts
index 82b8f7d6..26a6213a 100644
--- a/src/Lazy/index.ts
+++ b/src/Lazy/index.ts
@@ -16,6 +16,7 @@ import pluck from "./pluck";
 import prepend from "./prepend";
 import range from "./range";
 import reject from "./reject";
+import repeat from "./repeat";
 import split from "./split";
 import take from "./take";
 import takeUntil from "./takeUntil";
@@ -46,6 +47,7 @@ export {
   prepend,
   range,
   reject,
+  repeat,
   split,
   take,
   takeUntil,
diff --git a/src/Lazy/repeat.ts b/src/Lazy/repeat.ts
new file mode 100644
index 00000000..91561813
--- /dev/null
+++ b/src/Lazy/repeat.ts
@@ -0,0 +1,41 @@
+function* sync<T>(n: number, value: T): IterableIterator<T> {
+  for (let i = 0; i < n; i++) {
+    yield value;
+  }
+}
+
+/**
+ * Returns a Iterable/AsyncIterable of size n containing a specified value.
+ *
+ * @example
+ * ```ts
+ * const iter = repeat(2, 10);
+ * iter.next(); // {value: 10, done:false}
+ * iter.next(); // {value: 10, done:false}
+ * iter.next(); // {value: undefined, done:true}
+ *
+ * // with pipe
+ * pipe(
+ *   repeat(2, 10),
+ *   toArray,
+ * ); // [10, 10]
+ * ```
+ */
+function repeat<T>(n: number, value: T): IterableIterator<T>;
+
+function repeat<T>(n: number): (value: T) => IterableIterator<T>;
+
+function repeat<T>(
+  n: number,
+  value?: T,
+): IterableIterator<T> | ((value: T) => IterableIterator<T>) {
+  if (value === undefined) {
+    return (value: T) => {
+      return repeat(n, value);
+    };
+  }
+
+  return sync(n, value);
+}
+
+export default repeat;


Test patch:
diff --git a/test/Lazy/repeat.spec.ts b/test/Lazy/repeat.spec.ts
new file mode 100644
index 00000000..97a8e9ca
--- /dev/null
+++ b/test/Lazy/repeat.spec.ts
@@ -0,0 +1,20 @@
+import { pipe, toArray } from "../../src";
+import repeat from "../../src/Lazy/repeat";
+
+describe("repeat", function () {
+  it.each([
+    [5, 4, [4, 4, 4, 4, 4]],
+    [4, "a", ["a", "a", "a", "a"]],
+    [2, Promise.resolve("a"), [Promise.resolve("a"), Promise.resolve("a")]],
+  ])(
+    "should repeat returning specified value %i %s",
+    function (n, value, result) {
+      expect(toArray(repeat(n, value))).toEqual(result);
+    },
+  );
+
+  it("should be able to be used as a curried function in the pipeline", function () {
+    const res = pipe(5, repeat(4), toArray);
+    expect(res).toEqual([5, 5, 5, 5]);
+  });
+});
diff --git a/type-check/Lazy/repeat.test.ts b/type-check/Lazy/repeat.test.ts
new file mode 100644
index 00000000..74c8ca90
--- /dev/null
+++ b/type-check/Lazy/repeat.test.ts
@@ -0,0 +1,16 @@
+import * as Test from "../../src/types/Test";
+import { pipe, repeat } from "../../src";
+
+const { checks, check } = Test;
+
+const res1 = repeat(2, 5);
+const res2 = repeat(2, "5");
+const res3 = repeat(2, Promise.resolve(5));
+const res4 = pipe(5, repeat(2));
+
+checks([
+  check<typeof res1, IterableIterator<number>, Test.Pass>(),
+  check<typeof res2, IterableIterator<string>, Test.Pass>(),
+  check<typeof res3, IterableIterator<Promise<number>>, Test.Pass>(),
+  check<typeof res4, IterableIterator<number>, Test.Pass>(),
+]);