Repository: marpple/FxTS (ts)

Issue:
The empty array result of the `sum` function is '0'
# Suggestion

<!--
  Please fill in each section completely. Thank you!
-->

## ⭐ Suggestion

<!-- What would you like to be added? -->

If an empty array is entered as the argument value of the [sum function](https://fxts.dev/docs/sum), undefined is output.
Returning 0 seems more natural.

as-is
```ts
const result = pipe(
 [], 
 sum
);

// result undefined
```


to-be
```ts
const result = pipe(
 [], 
 sum
);

// result 0
```




## 💻 Use Cases

<!-- What do you want to use this for? -->


Pull request:
fix(sum): sum function logic
- only supoort number type
- empty array returns zero

Fixes #156 


Patch:
diff --git a/src/sum.ts b/src/sum.ts
index 4a6c800d..af658e06 100644
--- a/src/sum.ts
+++ b/src/sum.ts
@@ -1,6 +1,5 @@
 import add from "./add";
 import reduce from "./reduce";
-import ReturnValueType from "./types/ReturnValueType";
 import { isAsyncIterable, isIterable } from "./_internal/utils";
 
 /**
@@ -8,25 +7,28 @@ import { isAsyncIterable, isIterable } from "./_internal/utils";
  *
  * @example
  * ```ts
+ * sum([]); // 0
  * sum([1, 2, 3, 4]); // 10
- * sum(['a', 'b', 'c']); // 'abc'
  * await sum(toAsync([1, 2, 3, 4])); // 10
- * await sum(toAsync(['a', 'b', 'c'])); // 'abc'
  * ```
  */
-function sum<
-  A extends
-    | Iterable<number>
-    | AsyncIterable<number>
-    | Iterable<string>
-    | AsyncIterable<string>,
->(iterable: A): ReturnValueType<A> {
-  if (isIterable(iterable)) {
-    return reduce(add, iterable) as ReturnValueType<A>;
-  }
-
-  if (isAsyncIterable(iterable)) {
-    return reduce(add, iterable) as ReturnValueType<A>;
+function sum<A extends Iterable<number> | AsyncIterable<number>>(
+  iterable: A,
+): A extends Iterable<number>
+  ? number
+  : A extends AsyncIterable<number>
+  ? Promise<number>
+  : never;
+// TODO The signature and implementation type are different.
+function sum<A extends Iterable<number> | AsyncIterable<number>>(
+  iterable: A,
+): number | Promise<number> {
+  if (Array.isArray(iterable)) {
+    return iterable.reduce(add, 0);
+  } else if (isIterable(iterable)) {
+    return reduce<number, number>((a, b) => add(a, b), 0, iterable);
+  } else if (isAsyncIterable(iterable)) {
+    return reduce<number, number>(add, Promise.resolve(0), iterable);
   }
 
   throw new TypeError("'iterable' must be type of Iterable or AsyncIterable");


Test patch:
diff --git a/test/sum.spec.ts b/test/sum.spec.ts
index 0ff1d911..2b0fd9c1 100644
--- a/test/sum.spec.ts
+++ b/test/sum.spec.ts
@@ -4,7 +4,7 @@ describe("sum", function () {
   describe("sync", function () {
     it.each([
       [[1, 2, 3], 6],
-      [["a", "b", "c"], "abc"],
+      [[], 0],
     ])("should sum all elements %s %s", function (iterable, result) {
       expect(sum(iterable as Iterable<any>)).toEqual(result);
     });
@@ -12,15 +12,15 @@ describe("sum", function () {
     it("should be able to be used as a curried function in the pipeline", function () {
       const res1 = pipe([1, 2, 3], sum);
       expect(res1).toEqual(6);
-      const res2 = pipe(["a", "b", "c"], sum);
-      expect(res2).toEqual("abc");
+      const res2 = pipe([], sum);
+      expect(res2).toEqual(0);
     });
   });
 
   describe("async", function () {
     it.each([
       [[1, 2, 3], 6],
-      [["a", "b", "c"], "abc"],
+      [[], 0],
     ])("should sum all elements %s %s", async function (iterable, result) {
       expect(await sum(toAsync(iterable as Iterable<any>))).toEqual(result);
     });
@@ -28,8 +28,8 @@ describe("sum", function () {
     it("should be able to be used as a curried function in the pipeline", async function () {
       const res1 = await pipe([1, 2, 3], toAsync, sum);
       expect(res1).toEqual(6);
-      const res2 = await pipe(["a", "b", "c"], toAsync, sum);
-      expect(res2).toEqual("abc");
+      const res2 = await pipe([], toAsync, sum);
+      expect(res2).toEqual(0);
     });
   });
 });
diff --git a/type-check/sum.test.ts b/type-check/sum.test.ts
index fe536315..92425cc0 100644
--- a/type-check/sum.test.ts
+++ b/type-check/sum.test.ts
@@ -3,21 +3,18 @@ import { sum, pipe, toAsync } from "../src";
 
 const { checks, check } = Test;
 
-// const res0 = sum([1, 'a']); // error
+const res0 = sum([]);
 const res1 = sum([1, 2]);
-const res2 = sum(["a", "b"]);
-const res3 = sum(toAsync([1, 2]));
+const res2 = sum(toAsync([1, 2]));
+const res3 = pipe([], sum);
 const res4 = pipe([1, 2], sum);
-const res5 = pipe(["a", "b"], sum);
-const res6 = pipe([1, 2], toAsync, sum);
-const res7 = pipe(["a", "b"], toAsync, sum);
+const res5 = pipe([1, 2], toAsync, sum);
 
 checks([
+  check<typeof res0, number, Test.Pass>(),
   check<typeof res1, number, Test.Pass>(),
-  check<typeof res2, string, Test.Pass>(),
-  check<typeof res3, Promise<number>, Test.Pass>(),
+  check<typeof res2, Promise<number>, Test.Pass>(),
+  check<typeof res3, number, Test.Pass>(),
   check<typeof res4, number, Test.Pass>(),
-  check<typeof res5, string, Test.Pass>(),
-  check<typeof res6, Promise<number>, Test.Pass>(),
-  check<typeof res7, Promise<string>, Test.Pass>(),
+  check<typeof res5, Promise<number>, Test.Pass>(),
 ]);