es-toolkit 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (303) hide show
  1. package/.vscode/extensions.json +7 -0
  2. package/.vscode/settings.json +10 -0
  3. package/.yarn/sdks/eslint/bin/eslint.js +20 -0
  4. package/.yarn/sdks/eslint/lib/api.js +20 -0
  5. package/.yarn/sdks/eslint/lib/unsupported-api.js +20 -0
  6. package/.yarn/sdks/eslint/package.json +14 -0
  7. package/.yarn/sdks/integrations.yml +5 -0
  8. package/.yarn/sdks/prettier/bin/prettier.cjs +20 -0
  9. package/.yarn/sdks/prettier/index.cjs +20 -0
  10. package/.yarn/sdks/prettier/package.json +7 -0
  11. package/.yarn/sdks/typescript/bin/tsc +20 -0
  12. package/.yarn/sdks/typescript/bin/tsserver +20 -0
  13. package/.yarn/sdks/typescript/lib/tsc.js +20 -0
  14. package/.yarn/sdks/typescript/lib/tsserver.js +225 -0
  15. package/.yarn/sdks/typescript/lib/tsserverlibrary.js +225 -0
  16. package/.yarn/sdks/typescript/lib/typescript.js +20 -0
  17. package/.yarn/sdks/typescript/package.json +10 -0
  18. package/babel.config.js +6 -0
  19. package/coverage/.tmp/coverage-0.json +1 -0
  20. package/coverage/.tmp/coverage-1.json +1 -0
  21. package/coverage/.tmp/coverage-10.json +1 -0
  22. package/coverage/.tmp/coverage-11.json +1 -0
  23. package/coverage/.tmp/coverage-12.json +1 -0
  24. package/coverage/.tmp/coverage-13.json +1 -0
  25. package/coverage/.tmp/coverage-14.json +1 -0
  26. package/coverage/.tmp/coverage-15.json +1 -0
  27. package/coverage/.tmp/coverage-16.json +1 -0
  28. package/coverage/.tmp/coverage-17.json +1 -0
  29. package/coverage/.tmp/coverage-18.json +1 -0
  30. package/coverage/.tmp/coverage-19.json +1 -0
  31. package/coverage/.tmp/coverage-2.json +1 -0
  32. package/coverage/.tmp/coverage-20.json +1 -0
  33. package/coverage/.tmp/coverage-21.json +1 -0
  34. package/coverage/.tmp/coverage-22.json +1 -0
  35. package/coverage/.tmp/coverage-23.json +1 -0
  36. package/coverage/.tmp/coverage-24.json +1 -0
  37. package/coverage/.tmp/coverage-25.json +1 -0
  38. package/coverage/.tmp/coverage-26.json +1 -0
  39. package/coverage/.tmp/coverage-27.json +1 -0
  40. package/coverage/.tmp/coverage-28.json +1 -0
  41. package/coverage/.tmp/coverage-29.json +1 -0
  42. package/coverage/.tmp/coverage-3.json +1 -0
  43. package/coverage/.tmp/coverage-30.json +1 -0
  44. package/coverage/.tmp/coverage-4.json +1 -0
  45. package/coverage/.tmp/coverage-5.json +1 -0
  46. package/coverage/.tmp/coverage-6.json +1 -0
  47. package/coverage/.tmp/coverage-7.json +1 -0
  48. package/coverage/.tmp/coverage-8.json +1 -0
  49. package/coverage/.tmp/coverage-9.json +1 -0
  50. package/dist/array/chunk.d.ts +8 -0
  51. package/dist/array/chunk.spec.d.ts +1 -0
  52. package/dist/array/difference.d.ts +7 -0
  53. package/dist/array/difference.spec.d.ts +1 -0
  54. package/dist/array/differenceBy.d.ts +8 -0
  55. package/dist/array/differenceBy.spec.d.ts +1 -0
  56. package/dist/array/differenceWith.d.ts +8 -0
  57. package/dist/array/differenceWith.spec.d.ts +1 -0
  58. package/dist/array/drop.d.ts +7 -0
  59. package/dist/array/drop.spec.d.ts +1 -0
  60. package/dist/array/dropRight.d.ts +7 -0
  61. package/dist/array/dropRight.spec.d.ts +1 -0
  62. package/dist/array/dropRightWhile.d.ts +7 -0
  63. package/dist/array/dropRightWhile.spec.d.ts +1 -0
  64. package/dist/array/dropWhile.d.ts +7 -0
  65. package/dist/array/dropWhile.spec.d.ts +1 -0
  66. package/dist/array/groupBy.d.ts +1 -0
  67. package/dist/array/index.d.ts +30 -0
  68. package/dist/array/index.js +778 -0
  69. package/dist/array/intersection.d.ts +11 -0
  70. package/dist/array/intersection.spec.d.ts +1 -0
  71. package/dist/array/intersectionBy.d.ts +12 -0
  72. package/dist/array/intersectionBy.spec.d.ts +1 -0
  73. package/dist/array/intersectionWith.d.ts +12 -0
  74. package/dist/array/intersectionWith.spec.d.ts +1 -0
  75. package/dist/array/partition.d.ts +8 -0
  76. package/dist/array/partition.spec.d.ts +1 -0
  77. package/dist/array/sample.d.ts +7 -0
  78. package/dist/array/sample.spec.d.ts +1 -0
  79. package/dist/array/shuffle.d.ts +7 -0
  80. package/dist/array/shuffle.spec.d.ts +1 -0
  81. package/dist/array/take.d.ts +23 -0
  82. package/dist/array/take.spec.d.ts +1 -0
  83. package/dist/array/takeRight.d.ts +23 -0
  84. package/dist/array/takeRight.spec.d.ts +1 -0
  85. package/dist/array/takeRightWhile.d.ts +18 -0
  86. package/dist/array/takeRightWhile.spec.d.ts +1 -0
  87. package/dist/array/takeWhile.d.ts +19 -0
  88. package/dist/array/takeWhile.spec.d.ts +1 -0
  89. package/dist/array/union.d.ts +10 -0
  90. package/dist/array/union.spec.d.ts +1 -0
  91. package/dist/array/unionBy.d.ts +24 -0
  92. package/dist/array/unionBy.spec.d.ts +1 -0
  93. package/dist/array/unionWith.d.ts +14 -0
  94. package/dist/array/unionWith.spec.d.ts +1 -0
  95. package/dist/array/uniq.d.ts +14 -0
  96. package/dist/array/uniq.spec.d.ts +1 -0
  97. package/dist/array/uniqBy.d.ts +12 -0
  98. package/dist/array/uniqBy.spec.d.ts +1 -0
  99. package/dist/array/uniqWith.d.ts +12 -0
  100. package/dist/array/uniqWith.spec.d.ts +1 -0
  101. package/dist/array/xor.d.ts +19 -0
  102. package/dist/array/xor.spec.d.ts +1 -0
  103. package/dist/array/xorBy.d.ts +20 -0
  104. package/dist/array/xorBy.spec.d.ts +1 -0
  105. package/dist/array/xorWith.d.ts +19 -0
  106. package/dist/array/xorWith.spec.d.ts +1 -0
  107. package/dist/array/zip.d.ts +13 -0
  108. package/dist/array/zip.spec.d.ts +1 -0
  109. package/dist/array/zipWith.d.ts +9 -0
  110. package/dist/array/zipWith.spec.d.ts +1 -0
  111. package/dist/function/debounce.d.ts +24 -0
  112. package/dist/function/debounce.spec.d.ts +1 -0
  113. package/dist/function/index.d.ts +3 -0
  114. package/dist/function/index.js +113 -0
  115. package/dist/function/once.d.ts +18 -0
  116. package/dist/function/once.spec.d.ts +1 -0
  117. package/dist/function/throttle.d.ts +26 -0
  118. package/dist/function/throttle.spec.d.ts +1 -0
  119. package/dist/index.d.ts +6 -0
  120. package/dist/index.js +1111 -0
  121. package/dist/math/clamp.d.ts +11 -0
  122. package/dist/math/clamp.spec.d.ts +1 -0
  123. package/dist/math/index.d.ts +3 -0
  124. package/dist/math/index.js +63 -0
  125. package/dist/math/round.d.ts +13 -0
  126. package/dist/math/round.spec.d.ts +1 -0
  127. package/dist/math/sum.d.ts +13 -0
  128. package/dist/math/sum.spec.d.ts +1 -0
  129. package/dist/object/index.d.ts +4 -0
  130. package/dist/object/index.js +176 -0
  131. package/dist/object/omit.d.ts +7 -0
  132. package/dist/object/omit.spec.d.ts +1 -0
  133. package/dist/object/omitBy.d.ts +1 -0
  134. package/dist/object/pick.d.ts +7 -0
  135. package/dist/object/pick.spec.d.ts +1 -0
  136. package/dist/object/pickBy.d.ts +1 -0
  137. package/dist/predicate/index.d.ts +4 -0
  138. package/dist/predicate/index.js +50 -0
  139. package/dist/predicate/isNil.d.ts +6 -0
  140. package/dist/predicate/isNil.spec.d.ts +1 -0
  141. package/dist/predicate/isNotNil.d.ts +12 -0
  142. package/dist/predicate/isNotNil.spec.d.ts +1 -0
  143. package/dist/predicate/isNull.d.ts +6 -0
  144. package/dist/predicate/isNull.spec.d.ts +1 -0
  145. package/dist/predicate/isUndefined.d.ts +6 -0
  146. package/dist/predicate/isUndefined.spec.d.ts +1 -0
  147. package/dist/promise/delay.d.ts +6 -0
  148. package/dist/promise/delay.spec.d.ts +1 -0
  149. package/dist/promise/index.d.ts +1 -0
  150. package/dist/promise/index.js +16 -0
  151. package/esm/_virtual/_rollupPluginBabelHelpers.mjs +163 -0
  152. package/esm/array/_virtual/_rollupPluginBabelHelpers.mjs +114 -0
  153. package/esm/array/chunk.mjs +35 -0
  154. package/esm/array/difference.mjs +13 -0
  155. package/esm/array/differenceBy.mjs +17 -0
  156. package/esm/array/differenceWith.mjs +16 -0
  157. package/esm/array/drop.mjs +11 -0
  158. package/esm/array/dropRight.mjs +11 -0
  159. package/esm/array/dropRightWhile.mjs +15 -0
  160. package/esm/array/dropWhile.mjs +14 -0
  161. package/esm/array/groupBy.mjs +5 -0
  162. package/esm/array/index.mjs +30 -0
  163. package/esm/array/intersection.mjs +17 -0
  164. package/esm/array/intersectionBy.mjs +21 -0
  165. package/esm/array/intersectionWith.mjs +20 -0
  166. package/esm/array/partition.mjs +32 -0
  167. package/esm/array/sample.mjs +12 -0
  168. package/esm/array/shuffle.mjs +20 -0
  169. package/esm/array/take.mjs +27 -0
  170. package/esm/array/takeRight.mjs +30 -0
  171. package/esm/array/takeRightWhile.mjs +27 -0
  172. package/esm/array/takeWhile.mjs +41 -0
  173. package/esm/array/union.mjs +19 -0
  174. package/esm/array/unionBy.mjs +38 -0
  175. package/esm/array/unionWith.mjs +21 -0
  176. package/esm/array/uniq.mjs +18 -0
  177. package/esm/array/uniqBy.mjs +20 -0
  178. package/esm/array/uniqWith.mjs +39 -0
  179. package/esm/array/xor.mjs +27 -0
  180. package/esm/array/xorBy.mjs +30 -0
  181. package/esm/array/xorWith.mjs +29 -0
  182. package/esm/array/zip.mjs +40 -0
  183. package/esm/array/zipWith.mjs +31 -0
  184. package/esm/function/debounce.mjs +39 -0
  185. package/esm/function/index.mjs +3 -0
  186. package/esm/function/once.mjs +32 -0
  187. package/esm/function/throttle.mjs +38 -0
  188. package/esm/index.mjs +45 -0
  189. package/esm/math/clamp.mjs +18 -0
  190. package/esm/math/index.mjs +3 -0
  191. package/esm/math/round.mjs +19 -0
  192. package/esm/math/sum.mjs +22 -0
  193. package/esm/object/_virtual/_rollupPluginBabelHelpers.mjs +115 -0
  194. package/esm/object/index.mjs +4 -0
  195. package/esm/object/omit.mjs +26 -0
  196. package/esm/object/omitBy.mjs +5 -0
  197. package/esm/object/pick.mjs +26 -0
  198. package/esm/object/pickBy.mjs +5 -0
  199. package/esm/predicate/index.mjs +4 -0
  200. package/esm/predicate/isNil.mjs +10 -0
  201. package/esm/predicate/isNotNil.mjs +16 -0
  202. package/esm/predicate/isNull.mjs +10 -0
  203. package/esm/predicate/isUndefined.mjs +10 -0
  204. package/esm/promise/delay.mjs +12 -0
  205. package/esm/promise/index.mjs +1 -0
  206. package/package.json +94 -0
  207. package/rollup.config.js +5 -0
  208. package/src/array/chunk.spec.ts +27 -0
  209. package/src/array/chunk.ts +24 -0
  210. package/src/array/difference.spec.ts +10 -0
  211. package/src/array/difference.ts +11 -0
  212. package/src/array/differenceBy.spec.ts +9 -0
  213. package/src/array/differenceBy.ts +14 -0
  214. package/src/array/differenceWith.spec.ts +8 -0
  215. package/src/array/differenceWith.ts +14 -0
  216. package/src/array/drop.spec.ts +9 -0
  217. package/src/array/drop.ts +9 -0
  218. package/src/array/dropRight.spec.ts +9 -0
  219. package/src/array/dropRight.ts +9 -0
  220. package/src/array/dropRightWhile.spec.ts +16 -0
  221. package/src/array/dropRightWhile.ts +13 -0
  222. package/src/array/dropWhile.spec.ts +14 -0
  223. package/src/array/dropWhile.ts +10 -0
  224. package/src/array/groupBy.ts +3 -0
  225. package/src/array/index.ts +30 -0
  226. package/src/array/intersection.spec.ts +11 -0
  227. package/src/array/intersection.ts +15 -0
  228. package/src/array/intersectionBy.spec.ts +9 -0
  229. package/src/array/intersectionBy.ts +18 -0
  230. package/src/array/intersectionWith.spec.ts +9 -0
  231. package/src/array/intersectionWith.ts +18 -0
  232. package/src/array/partition.spec.ts +23 -0
  233. package/src/array/partition.ts +21 -0
  234. package/src/array/sample.spec.ts +11 -0
  235. package/src/array/sample.ts +10 -0
  236. package/src/array/shuffle.spec.ts +11 -0
  237. package/src/array/shuffle.ts +18 -0
  238. package/src/array/take.spec.ts +25 -0
  239. package/src/array/take.ts +25 -0
  240. package/src/array/takeRight.spec.ts +25 -0
  241. package/src/array/takeRight.ts +29 -0
  242. package/src/array/takeRightWhile.spec.ts +16 -0
  243. package/src/array/takeRightWhile.ts +26 -0
  244. package/src/array/takeWhile.spec.ts +34 -0
  245. package/src/array/takeWhile.ts +31 -0
  246. package/src/array/union.spec.ts +10 -0
  247. package/src/array/union.ts +14 -0
  248. package/src/array/unionBy.spec.ts +12 -0
  249. package/src/array/unionBy.ts +35 -0
  250. package/src/array/unionWith.spec.ts +23 -0
  251. package/src/array/unionWith.ts +18 -0
  252. package/src/array/uniq.spec.ts +8 -0
  253. package/src/array/uniq.ts +16 -0
  254. package/src/array/uniqBy.spec.ts +8 -0
  255. package/src/array/uniqBy.ts +17 -0
  256. package/src/array/uniqWith.spec.ts +16 -0
  257. package/src/array/uniqWith.ts +29 -0
  258. package/src/array/xor.spec.ts +13 -0
  259. package/src/array/xor.ts +25 -0
  260. package/src/array/xorBy.spec.ts +16 -0
  261. package/src/array/xorBy.ts +29 -0
  262. package/src/array/xorWith.spec.ts +16 -0
  263. package/src/array/xorWith.ts +28 -0
  264. package/src/array/zip.spec.ts +14 -0
  265. package/src/array/zip.ts +34 -0
  266. package/src/array/zipWith.spec.ts +13 -0
  267. package/src/array/zipWith.ts +23 -0
  268. package/src/function/debounce.spec.ts +76 -0
  269. package/src/function/debounce.ts +42 -0
  270. package/src/function/index.ts +3 -0
  271. package/src/function/once.spec.ts +31 -0
  272. package/src/function/once.ts +34 -0
  273. package/src/function/throttle.spec.ts +32 -0
  274. package/src/function/throttle.ts +39 -0
  275. package/src/index.ts +6 -0
  276. package/src/math/clamp.spec.ts +18 -0
  277. package/src/math/clamp.ts +17 -0
  278. package/src/math/index.ts +3 -0
  279. package/src/math/round.spec.ts +53 -0
  280. package/src/math/round.ts +16 -0
  281. package/src/math/sum.spec.ts +29 -0
  282. package/src/math/sum.ts +17 -0
  283. package/src/object/index.ts +4 -0
  284. package/src/object/omit.spec.ts +10 -0
  285. package/src/object/omit.ts +15 -0
  286. package/src/object/omitBy.ts +3 -0
  287. package/src/object/pick.spec.ts +10 -0
  288. package/src/object/pick.ts +15 -0
  289. package/src/object/pickBy.ts +3 -0
  290. package/src/predicate/index.ts +4 -0
  291. package/src/predicate/isNil.spec.ts +23 -0
  292. package/src/predicate/isNil.ts +8 -0
  293. package/src/predicate/isNotNil.spec.ts +29 -0
  294. package/src/predicate/isNotNil.ts +14 -0
  295. package/src/predicate/isNull.spec.ts +23 -0
  296. package/src/predicate/isNull.ts +8 -0
  297. package/src/predicate/isUndefined.spec.ts +23 -0
  298. package/src/predicate/isUndefined.ts +8 -0
  299. package/src/promise/delay.spec.ts +13 -0
  300. package/src/promise/delay.ts +10 -0
  301. package/src/promise/index.ts +1 -0
  302. package/tsconfig.json +12 -0
  303. package/vitest.config.mts +13 -0
@@ -0,0 +1,76 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { debounce } from './debounce'; // adjust the import path as necessary
3
+ import { delay } from '../promise';
4
+
5
+ describe('debounce', () => {
6
+ it('should debounce function calls', async () => {
7
+ const func = vi.fn();
8
+ const waitMs = 50;
9
+ const debouncedFunc = debounce(func, waitMs);
10
+
11
+ debouncedFunc();
12
+ debouncedFunc();
13
+ debouncedFunc();
14
+
15
+ await delay(waitMs * 2)
16
+
17
+ expect(func).toHaveBeenCalledTimes(1);
18
+ });
19
+
20
+ it('should delay the function call by the specified wait time', async () => {
21
+ const func = vi.fn();
22
+ const waitMs = 50;
23
+ const debouncedFunc = debounce(func, waitMs);
24
+
25
+ debouncedFunc();
26
+ await delay(waitMs / 2);
27
+ expect(func).not.toHaveBeenCalled();
28
+
29
+ await delay(waitMs / 2 + 1);
30
+ expect(func).toHaveBeenCalledTimes(1);
31
+ });
32
+
33
+ it('should reset the wait time if called again before wait time ends', async () => {
34
+ const func = vi.fn();
35
+ const waitMs = 50;
36
+ const debouncedFunc = debounce(func, waitMs);
37
+
38
+ debouncedFunc();
39
+ await delay(waitMs / 2);
40
+ debouncedFunc();
41
+ await delay(waitMs / 2);
42
+ debouncedFunc();
43
+ await delay(waitMs / 2);
44
+ debouncedFunc();
45
+
46
+ expect(func).not.toHaveBeenCalled();
47
+
48
+ await delay(waitMs + 1);
49
+ expect(func).toHaveBeenCalledTimes(1);
50
+ });
51
+
52
+ it('should cancel the debounced function call', async () => {
53
+ const func = vi.fn();
54
+ const waitMs = 50;
55
+ const debouncedFunc = debounce(func, waitMs);
56
+
57
+ debouncedFunc();
58
+ debouncedFunc.cancel();
59
+ await delay(waitMs);
60
+
61
+ expect(func).not.toHaveBeenCalled();
62
+ });
63
+
64
+ it('should work correctly if the debounced function is called after the wait time', async () => {
65
+ const func = vi.fn();
66
+ const waitMs = 50;
67
+ const debouncedFunc = debounce(func, waitMs);
68
+
69
+ debouncedFunc();
70
+ await delay(waitMs + 1);
71
+ debouncedFunc();
72
+ await delay(waitMs + 1);
73
+
74
+ expect(func).toHaveBeenCalledTimes(2);
75
+ });
76
+ });
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Creates a debounced function that delays invoking the provided function until after `waitMs` milliseconds
3
+ * have elapsed since the last time the debounced function was invoked. The debounced function also has a `cancel`
4
+ * method to cancel any pending execution.
5
+ *
6
+ * @param {() => void} func - The function to debounce.
7
+ * @param {number} waitMs - The number of milliseconds to delay.
8
+ * @returns {{ (): void; cancel: () => void }} A new debounced function with a `cancel` method.
9
+ *
10
+ * @example
11
+ * const debouncedFunction = debounce(() => {
12
+ * console.log('Function executed');
13
+ * }, 1000);
14
+ *
15
+ * // Will log 'Function executed' after 1 second if not called again in that time
16
+ * debouncedFunction();
17
+ *
18
+ * // Will not log anything as the previous call is canceled
19
+ * debouncedFunction.cancel();
20
+ */
21
+ export function debounce(func: () => void, waitMs: number) {
22
+ let timeoutId: number | NodeJS.Timeout | null = null;
23
+
24
+ const debounced = function () {
25
+ if (timeoutId != null) {
26
+ clearTimeout(timeoutId);
27
+ }
28
+
29
+
30
+ timeoutId = setTimeout(() => {
31
+ func();
32
+ }, waitMs);
33
+ };
34
+
35
+ debounced.cancel = function () {
36
+ if (timeoutId != null) {
37
+ clearTimeout(timeoutId);
38
+ }
39
+ }
40
+
41
+ return debounced;
42
+ }
@@ -0,0 +1,3 @@
1
+ export { debounce } from './debounce';
2
+ export { once } from './once';
3
+ export { throttle } from './throttle';
@@ -0,0 +1,31 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { once } from './once'; // adjust the import path as necessary
3
+
4
+ describe('once', () => {
5
+ it('should call the function only once', () => {
6
+ const func = vi.fn(() => 42);
7
+ const onceFunc = once(func);
8
+
9
+ expect(onceFunc()).toBe(42);
10
+ expect(onceFunc()).toBe(42);
11
+ expect(func).toHaveBeenCalledTimes(1);
12
+ });
13
+
14
+ it('should work with functions returning undefined', () => {
15
+ const func = vi.fn(() => undefined);
16
+ const onceFunc = once(func);
17
+
18
+ expect(onceFunc()).toBeUndefined();
19
+ expect(onceFunc()).toBeUndefined();
20
+ expect(func).toHaveBeenCalledTimes(1);
21
+ });
22
+
23
+ it('should handle functions with no return value', () => {
24
+ const func = vi.fn(() => { console.log('Side effect'); });
25
+ const onceFunc = once(func);
26
+
27
+ onceFunc();
28
+ onceFunc();
29
+ expect(func).toHaveBeenCalledTimes(1);
30
+ });
31
+ });
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Creates a function that is restricted to invoking the provided function `func` once.
3
+ * Repeated calls to the function will return the value from the first invocation.
4
+ *
5
+ * @template F - The type of the function to be invoked once.
6
+ * @param {F} func - The function to restrict.
7
+ * @returns {F} A new function that invokes `func` once and caches the result.
8
+ *
9
+ * @example
10
+ * const initialize = once(() => {
11
+ * console.log('Initialized!');
12
+ * return true;
13
+ * });
14
+ *
15
+ * initialize(); // Logs: 'Initialized!' and returns true
16
+ * initialize(); // Returns true without logging
17
+ */
18
+ export function once<F extends () => any>(func: F): F {
19
+ let called = false;
20
+ let cache: ReturnType<F> | undefined;
21
+
22
+ return function () {
23
+ if (called) {
24
+ return cache;
25
+ }
26
+
27
+ const result = func();
28
+
29
+ called = true;
30
+ cache = result;
31
+
32
+ return result;
33
+ } as F;
34
+ }
@@ -0,0 +1,32 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { throttle } from './throttle';
3
+ import { delay } from '../promise';
4
+
5
+ describe('throttle', () => {
6
+ it('should throttle function calls', async () => {
7
+ const func = vi.fn();
8
+ const throttledFunc = throttle(func, 100);
9
+
10
+ throttledFunc();
11
+ throttledFunc();
12
+ throttledFunc();
13
+
14
+ expect(func).toHaveBeenCalledTimes(1);
15
+ });
16
+
17
+ it('should execute the function immediately if not called within the wait time', async () => {
18
+ const func = vi.fn();
19
+ const waitMs = 50;
20
+ const throttledFunc = throttle(func, waitMs);
21
+
22
+ throttledFunc();
23
+ await delay(waitMs / 2);
24
+ throttledFunc();
25
+
26
+ expect(func).toHaveBeenCalledTimes(1);
27
+
28
+ await delay(waitMs / 2 + 1);
29
+ throttledFunc();
30
+ expect(func).toHaveBeenCalledTimes(2);
31
+ });
32
+ });
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Creates a throttled function that only invokes the provided function at most once
3
+ * per every `throttleMs` milliseconds. Subsequent calls to the throttled function
4
+ * within the wait time will not trigger the execution of the original function.
5
+ *
6
+ * @param {() => void} func - The function to throttle.
7
+ * @param {number} throttleMs - The number of milliseconds to throttle executions to.
8
+ * @returns {() => void} A new throttled function.
9
+ *
10
+ * @example
11
+ * const throttledFunction = throttle(() => {
12
+ * console.log('Function executed');
13
+ * }, 1000);
14
+ *
15
+ * // Will log 'Function executed' immediately
16
+ * throttledFunction();
17
+ *
18
+ * // Will not log anything as it is within the throttle time
19
+ * throttledFunction();
20
+ *
21
+ * // After 1 second
22
+ * setTimeout(() => {
23
+ * throttledFunction(); // Will log 'Function executed'
24
+ * }, 1000);
25
+ */
26
+ export function throttle(func: () => void, throttleMs: number) {
27
+ let lastCallTime: number | null;
28
+
29
+ const throttledFunction = function () {
30
+ const now = Date.now();
31
+
32
+ if (lastCallTime == null || now - lastCallTime >= throttleMs) {
33
+ lastCallTime = now;
34
+ func();
35
+ }
36
+ }
37
+
38
+ return throttledFunction;
39
+ }
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from './array';
2
+ export * from './function';
3
+ export * from './math';
4
+ export * from './object';
5
+ export * from './predicate';
6
+ export * from './promise';
@@ -0,0 +1,18 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { clamp } from "./clamp";
3
+
4
+ describe("clamp function", () => {
5
+ it("works with max", () => {
6
+ expect(clamp(3, 5)).toBe(3);
7
+ expect(clamp(10, 6)).toBe(6);
8
+ expect(clamp(6, 10)).toBe(6);
9
+ });
10
+
11
+ it("works with max and min", () => {
12
+ expect(clamp(3, 5, 10)).toBe(5);
13
+ expect(clamp(10, 6, 10)).toBe(10);
14
+ expect(clamp(6, 10, 10)).toBe(10);
15
+ expect(clamp(7, 5, 10)).toBe(7);
16
+ expect(clamp(100, 5, 6)).toBe(6);
17
+ });
18
+ });
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @name clamp
3
+ * @description Checks if `value` is within the bounds, if not return the closest bound (bound1: min, bound2: max)
4
+ * function clamp(value: number, bound1: number, bound2?: number): number
5
+ * @example
6
+ * clamp(3, 1) // 3
7
+ * clamp(3, 1, 5) // 3
8
+ * clamp(3, 5) // 5
9
+ * clamp(7, 3, 5) // 5
10
+ */
11
+ export function clamp(value: number, bound1: number, bound2?: number): number {
12
+ if (bound2 == null) {
13
+ return Math.min(value, bound1);
14
+ }
15
+
16
+ return Math.min(Math.max(value, bound1), bound2);
17
+ }
@@ -0,0 +1,3 @@
1
+ export { clamp } from './clamp';
2
+ export { round } from './round';
3
+ export { sum } from './sum';
@@ -0,0 +1,53 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { round } from "./round";
3
+
4
+ describe("round function", () => {
5
+ it("rounds a number to zero decimal places by default", () => {
6
+ expect(round(1.5)).toBe(2);
7
+ expect(round(1.4)).toBe(1);
8
+ // JavaScript는 반올림 하는 부분이 정확히 음수 0.5라면 +∞방향, 즉, 정수로 반올림 한다.
9
+ // If the fractional portion is exactly 0.5, the argument is rounded to the next integer in the direction of +∞. (positive number)
10
+ expect(round(-1.5)).toBe(-1);
11
+ });
12
+
13
+ it("rounds a number to a specified number of decimal places", () => {
14
+ expect(round(1.2345, 2)).toBe(1.23);
15
+ expect(round(1.2365, 2)).toBe(1.24);
16
+ expect(round(-1.2345, 2)).toBe(-1.23);
17
+ expect(round(-1.2365, 2)).toBe(-1.24);
18
+ });
19
+
20
+ it("handles zero precision as default precision", () => {
21
+ expect(round(1.999)).toBe(2);
22
+ expect(round(-1.999)).toBe(-2);
23
+ });
24
+
25
+ it("handles negative numbers properly", () => {
26
+ // JavaScript는 반올림 하는 부분이 정확히 음수 0.5라면 +∞방향, 즉, 정수로 반올림 한다.
27
+ // If the fractional portion is exactly 0.5, the argument is rounded to the next integer in the direction of +∞. (positive number)
28
+ expect(round(-1.2345, 3)).toBe(-1.234);
29
+ expect(round(-1.2344, 3)).toBe(-1.234);
30
+ });
31
+
32
+ it("rounds correctly at high precision levels", () => {
33
+ expect(round(1.123456789, 5)).toBe(1.12346);
34
+ expect(round(-1.123456789, 5)).toBe(-1.12346);
35
+ });
36
+
37
+ it("rounds correctly with edge cases", () => {
38
+ expect(round(1.25, 1)).toBe(1.3);
39
+ // JavaScript는 반올림 하는 부분이 정확히 음수 0.5라면 +∞방향, 즉, 정수로 반올림 한다.
40
+ // If the fractional portion is exactly 0.5, the argument is rounded to the next integer in the direction of +∞. (positive number)
41
+ expect(round(-1.25, 1)).toBe(-1.2);
42
+ // JavaScript는 일반적인 다른 언어들과 다르게 Round half to even 으로 동작하지 않는다.
43
+ // The round function in JavaScript does not work as 'Round half to Even'
44
+ expect(round(-1.35, 1)).toBe(-1.3);
45
+ });
46
+ it("works with zero", () => {
47
+ expect(round(0)).toBe(0);
48
+ });
49
+
50
+ it("works with precision leading to no rounding", () => {
51
+ expect(round(8.88888, 5)).toBe(8.88888);
52
+ });
53
+ });
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @name round
3
+ * @description Rounds given number to given precision
4
+ * ```typescript
5
+ * function round(value: number, precision: number = 0): number
6
+ * ```
7
+ *
8
+ * @example
9
+ * round(1.2) === 1
10
+ * round(3.9) === 4
11
+ * round(8.5) === 9
12
+ */
13
+ export function round(value: number, precision: number = 0): number {
14
+ const multiplier = Math.pow(10, precision);
15
+ return Math.round(value * multiplier) / multiplier;
16
+ }
@@ -0,0 +1,29 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { sum } from "./sum";
3
+
4
+ describe("sum function", () => {
5
+ it("calculates the sum of a given numbers", () => {
6
+ const result = sum(1, 2, 3, 4);
7
+ expect(result).toBe(10);
8
+ });
9
+
10
+ it("calculates the sum of an array of numbers", () => {
11
+ const result = sum([1, 2, 3, 4]);
12
+ expect(result).toBe(10);
13
+ });
14
+
15
+ it("calculates the sum of an multiple array of numbers", () => {
16
+ const result = sum([1, 2], [3, 4]);
17
+ expect(result).toBe(10);
18
+ });
19
+
20
+ it("returns 0 for an empty array", () => {
21
+ const result = sum();
22
+ expect(result).toBe(0);
23
+ });
24
+
25
+ it("handles arrays with negative numbers", () => {
26
+ const result = sum([-1, -2, -3, 4]);
27
+ expect(result).toBe(-2);
28
+ });
29
+ });
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @name sum
3
+ * @description Return the sum of given values.
4
+ * ```typescript
5
+ * function sum(...nums: number[] | number[][]): number;
6
+ * ```
7
+ *
8
+ * @example
9
+ * sum(1, 2, 3) === 6
10
+ * sum(...[1, 2, 3]) === 6
11
+ * sum([1, 2, 3]) === 6
12
+ */
13
+ export function sum(...nums: number[] | number[][]) {
14
+ return nums.flat().reduce((acc, curr) => {
15
+ return acc + curr;
16
+ }, 0);
17
+ }
@@ -0,0 +1,4 @@
1
+ export { omit } from './omit';
2
+ export { omitBy } from './omitBy';
3
+ export { pick } from './pick';
4
+ export { pickBy } from './pickBy';
@@ -0,0 +1,10 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { omit } from "./omit";
3
+
4
+ describe("omit", () => {
5
+ it("should omit properties from an object", () => {
6
+ const object = { foo: 1, bar: 2, baz: 3 };
7
+
8
+ expect(omit(object, ['foo', 'bar'])).toEqual({ baz: 3 });
9
+ });
10
+ });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @name omit
3
+ * Omit properties from an object.
4
+ * @param obj The object to omit properties from
5
+ * @param keys The keys to omit from an object
6
+ */
7
+ export function omit<T, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> {
8
+ const result = { ...obj };
9
+
10
+ for (const key of keys) {
11
+ delete result[key];
12
+ }
13
+
14
+ return result as Omit<T, K>
15
+ }
@@ -0,0 +1,3 @@
1
+ export function omitBy() {
2
+ throw new Error('Not implemented');
3
+ }
@@ -0,0 +1,10 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { pick } from "./pick";
3
+
4
+ describe("pick", () => {
5
+ it("should pick properties from an object", () => {
6
+ const object = { foo: 1, bar: 2, baz: 3 };
7
+
8
+ expect(pick(object, ['foo', 'bar'])).toEqual({ foo: 1, bar: 2 });
9
+ });
10
+ });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @name pick
3
+ * Pick properties from an given object.
4
+ * @param obj The object to pick properties from
5
+ * @param keys The keys to pick from an object
6
+ */
7
+ export function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
8
+ const result = {} as Pick<T, K>;
9
+
10
+ for (const key of keys) {
11
+ result[key] = obj[key];
12
+ }
13
+
14
+ return result;
15
+ }
@@ -0,0 +1,3 @@
1
+ export function pickBy() {
2
+ throw new Error('Not implemented');
3
+ }
@@ -0,0 +1,4 @@
1
+ export { isNil } from './isNil';
2
+ export { isNotNil } from './isNotNil';
3
+ export { isNull } from './isNull';
4
+ export { isUndefined } from './isUndefined';
@@ -0,0 +1,23 @@
1
+ import { describe, expect, it } from "vitest"
2
+ import { isNil } from "./isNil"
3
+
4
+ describe('isNil', () => {
5
+ it('returns true if the value is null or undefined', () => {
6
+ expect(isNil(null)).toBe(true);
7
+ expect(isNil(undefined)).toBe(true);
8
+ });
9
+
10
+ it('returns false if the value is not null nor undefined', () => {
11
+ expect(isNil('')).toBe(false);
12
+ expect(isNil(123)).toBe(false);
13
+ })
14
+
15
+ it('can be used with TypeScript as a type predicate', () => {
16
+ const arr = [1, 2, null, 4, undefined];
17
+
18
+ const result = arr.filter(isNil);
19
+
20
+ // Here the type of result should be `null | undefined`.
21
+ expect(result).toStrictEqual([null, undefined]);
22
+ })
23
+ })
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @name isNil
3
+ * Checks if the given value is null or undefined.
4
+ * @param x The value to test if it is null or undefined
5
+ */
6
+ export function isNil(x: unknown): x is null | undefined {
7
+ return x == null || x == undefined;
8
+ }
@@ -0,0 +1,29 @@
1
+ import { describe, expect, it } from "vitest"
2
+ import { isNotNil } from "./isNotNil"
3
+
4
+ describe('isNotNil', () => {
5
+ it('returns false if the value is null or undefined', () => {
6
+ expect(isNotNil(null)).toBe(false);
7
+ expect(isNotNil(undefined)).toBe(false);
8
+ });
9
+
10
+ it('returns true if the value is not null nor undefined', () => {
11
+ expect(isNotNil('')).toBe(true);
12
+ expect(isNotNil(123)).toBe(true);
13
+ })
14
+
15
+ it('can be used with TypeScript as a type predicate', () => {
16
+ const arr1 = [1, 2, null, 4, undefined];
17
+ const arr2 = [1, 2, null];
18
+ const arr3 = [1, 2, 4, undefined];
19
+
20
+ const result1 = arr1.filter(isNotNil);
21
+ const result2 = arr2.filter(isNotNil);
22
+ const result3 = arr3.filter(isNotNil);
23
+
24
+ // Here the type of result should be `number[]`.
25
+ expect(result1).toStrictEqual([1, 2, 4]);
26
+ expect(result2).toStrictEqual([1, 2]);
27
+ expect(result3).toStrictEqual([1, 2, 4]);
28
+ })
29
+ })
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @name isNotNil
3
+ * Checks if the given value is not null nor undefined.
4
+ * The main use of this function is to used with TypeScript as a type predicate.
5
+ * @param x The value to test if it is not null nor undefined
6
+ * @example
7
+ * // Here the type of `arr` is (number | undefined)[]
8
+ * const arr = [1, undefined, 3];
9
+ * // Here the type of `result` is number[]
10
+ * const result = arr.filter(isNotNil);
11
+ */
12
+ export function isNotNil<T>(x: T | null | undefined): x is T {
13
+ return x != null && x != undefined;
14
+ }
@@ -0,0 +1,23 @@
1
+ import { describe, expect, it } from "vitest"
2
+ import { isNull } from "./isNull"
3
+
4
+ describe('isNull', () => {
5
+ it('returns true if the value is null', () => {
6
+ expect(isNull(null)).toBe(true);
7
+ });
8
+
9
+ it('returns false if the value is not null', () => {
10
+ expect(isNull(undefined)).toBe(false);
11
+ expect(isNull('')).toBe(false);
12
+ expect(isNull(123)).toBe(false);
13
+ })
14
+
15
+ it('can be used with TypeScript as a type predicate', () => {
16
+ const arr = [1, 2, null, 4, undefined];
17
+
18
+ const result = arr.filter(isNull);
19
+
20
+ // Here the type of result should be `null[]`.
21
+ expect(result).toStrictEqual([null]);
22
+ })
23
+ })
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @name isNull
3
+ * Checks if the given value is null.
4
+ * @param x The value to test if it is null
5
+ */
6
+ export function isNull(x: unknown): x is null {
7
+ return x === null;
8
+ }
@@ -0,0 +1,23 @@
1
+ import { describe, expect, it } from "vitest"
2
+ import { isUndefined } from "./isUndefined"
3
+
4
+ describe('isUndefined', () => {
5
+ it('returns true if the value is undefined', () => {
6
+ expect(isUndefined(undefined)).toBe(true);
7
+ });
8
+
9
+ it('returns false if the value is not undefined', () => {
10
+ expect(isUndefined(null)).toBe(false);
11
+ expect(isUndefined('')).toBe(false);
12
+ expect(isUndefined(123)).toBe(false);
13
+ })
14
+
15
+ it('can be used with TypeScript as a type predicate', () => {
16
+ const arr = [1, 2, null, 4, undefined];
17
+
18
+ const result = arr.filter(isUndefined);
19
+
20
+ // Here the type of result should be `null[]`.
21
+ expect(result).toStrictEqual([undefined]);
22
+ })
23
+ })
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @name isUndefined
3
+ * Checks if the given value is undefined.
4
+ * @param x The value to test if it is undefined
5
+ */
6
+ export function isUndefined(x: unknown): x is undefined {
7
+ return x === undefined;
8
+ }