ts-data-forge 1.0.0 → 1.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 (292) hide show
  1. package/README.md +1 -1
  2. package/dist/array/array-utils.d.mts +2617 -0
  3. package/dist/array/array-utils.d.mts.map +1 -0
  4. package/dist/array/array-utils.mjs +2915 -0
  5. package/dist/array/array-utils.mjs.map +1 -0
  6. package/dist/array/index.d.mts +3 -0
  7. package/dist/array/index.d.mts.map +1 -0
  8. package/dist/array/index.mjs +3 -0
  9. package/dist/array/index.mjs.map +1 -0
  10. package/dist/array/tuple-utils.d.mts +421 -0
  11. package/dist/array/tuple-utils.d.mts.map +1 -0
  12. package/dist/array/tuple-utils.mjs +391 -0
  13. package/dist/array/tuple-utils.mjs.map +1 -0
  14. package/dist/collections/imap-mapped.d.mts +445 -0
  15. package/dist/collections/imap-mapped.d.mts.map +1 -0
  16. package/dist/collections/imap-mapped.mjs +424 -0
  17. package/dist/collections/imap-mapped.mjs.map +1 -0
  18. package/dist/collections/imap.d.mts +359 -0
  19. package/dist/collections/imap.d.mts.map +1 -0
  20. package/dist/collections/imap.mjs +338 -0
  21. package/dist/collections/imap.mjs.map +1 -0
  22. package/dist/collections/index.d.mts +7 -0
  23. package/dist/collections/index.d.mts.map +1 -0
  24. package/dist/collections/index.mjs +7 -0
  25. package/dist/collections/index.mjs.map +1 -0
  26. package/dist/collections/iset-mapped.d.mts +576 -0
  27. package/dist/collections/iset-mapped.d.mts.map +1 -0
  28. package/dist/collections/iset-mapped.mjs +522 -0
  29. package/dist/collections/iset-mapped.mjs.map +1 -0
  30. package/dist/collections/iset.d.mts +426 -0
  31. package/dist/collections/iset.d.mts.map +1 -0
  32. package/dist/collections/iset.mjs +437 -0
  33. package/dist/collections/iset.mjs.map +1 -0
  34. package/dist/collections/queue.d.mts +190 -0
  35. package/dist/collections/queue.d.mts.map +1 -0
  36. package/dist/collections/queue.mjs +317 -0
  37. package/dist/collections/queue.mjs.map +1 -0
  38. package/dist/collections/stack.d.mts +210 -0
  39. package/dist/collections/stack.d.mts.map +1 -0
  40. package/dist/collections/stack.mjs +353 -0
  41. package/dist/collections/stack.mjs.map +1 -0
  42. package/dist/expect-type.d.mts +199 -0
  43. package/dist/expect-type.d.mts.map +1 -0
  44. package/dist/expect-type.mjs +201 -0
  45. package/dist/expect-type.mjs.map +1 -0
  46. package/dist/functional/index.d.mts +5 -0
  47. package/dist/functional/index.d.mts.map +1 -0
  48. package/dist/functional/index.mjs +5 -0
  49. package/dist/functional/index.mjs.map +1 -0
  50. package/dist/functional/match.d.mts +215 -0
  51. package/dist/functional/match.d.mts.map +1 -0
  52. package/dist/functional/match.mjs +139 -0
  53. package/dist/functional/match.mjs.map +1 -0
  54. package/dist/functional/optional.d.mts +517 -0
  55. package/dist/functional/optional.d.mts.map +1 -0
  56. package/dist/functional/optional.mjs +532 -0
  57. package/dist/functional/optional.mjs.map +1 -0
  58. package/dist/functional/pipe.d.mts +185 -0
  59. package/dist/functional/pipe.d.mts.map +1 -0
  60. package/dist/functional/pipe.mjs +129 -0
  61. package/dist/functional/pipe.mjs.map +1 -0
  62. package/dist/functional/result.d.mts +796 -0
  63. package/dist/functional/result.d.mts.map +1 -0
  64. package/dist/functional/result.mjs +844 -0
  65. package/dist/functional/result.mjs.map +1 -0
  66. package/dist/globals.d.mts +38 -0
  67. package/dist/guard/has-key.d.mts +100 -0
  68. package/dist/guard/has-key.d.mts.map +1 -0
  69. package/dist/guard/has-key.mjs +94 -0
  70. package/dist/guard/has-key.mjs.map +1 -0
  71. package/dist/guard/index.d.mts +8 -0
  72. package/dist/guard/index.d.mts.map +1 -0
  73. package/dist/guard/index.mjs +8 -0
  74. package/dist/guard/index.mjs.map +1 -0
  75. package/dist/guard/is-non-empty-string.d.mts +106 -0
  76. package/dist/guard/is-non-empty-string.d.mts.map +1 -0
  77. package/dist/guard/is-non-empty-string.mjs +108 -0
  78. package/dist/guard/is-non-empty-string.mjs.map +1 -0
  79. package/dist/guard/is-non-null-object.d.mts +105 -0
  80. package/dist/guard/is-non-null-object.d.mts.map +1 -0
  81. package/dist/guard/is-non-null-object.mjs +108 -0
  82. package/dist/guard/is-non-null-object.mjs.map +1 -0
  83. package/dist/guard/is-primitive.d.mts +146 -0
  84. package/dist/guard/is-primitive.d.mts.map +1 -0
  85. package/dist/guard/is-primitive.mjs +161 -0
  86. package/dist/guard/is-primitive.mjs.map +1 -0
  87. package/dist/guard/is-record.d.mts +151 -0
  88. package/dist/guard/is-record.d.mts.map +1 -0
  89. package/dist/guard/is-record.mjs +155 -0
  90. package/dist/guard/is-record.mjs.map +1 -0
  91. package/dist/guard/is-type.d.mts +430 -0
  92. package/dist/guard/is-type.d.mts.map +1 -0
  93. package/dist/guard/is-type.mjs +432 -0
  94. package/dist/guard/is-type.mjs.map +1 -0
  95. package/dist/guard/key-is-in.d.mts +158 -0
  96. package/dist/guard/key-is-in.d.mts.map +1 -0
  97. package/dist/guard/key-is-in.mjs +160 -0
  98. package/dist/guard/key-is-in.mjs.map +1 -0
  99. package/dist/index.d.mts +11 -0
  100. package/dist/index.d.mts.map +1 -0
  101. package/dist/index.mjs +61 -0
  102. package/dist/index.mjs.map +1 -0
  103. package/dist/iterator/index.d.mts +2 -0
  104. package/dist/iterator/index.d.mts.map +1 -0
  105. package/dist/iterator/index.mjs +2 -0
  106. package/dist/iterator/index.mjs.map +1 -0
  107. package/dist/iterator/range.d.mts +97 -0
  108. package/dist/iterator/range.d.mts.map +1 -0
  109. package/dist/iterator/range.mjs +130 -0
  110. package/dist/iterator/range.mjs.map +1 -0
  111. package/dist/json/index.d.mts +2 -0
  112. package/dist/json/index.d.mts.map +1 -0
  113. package/dist/json/index.mjs +2 -0
  114. package/dist/json/index.mjs.map +1 -0
  115. package/dist/json/json.d.mts +597 -0
  116. package/dist/json/json.d.mts.map +1 -0
  117. package/dist/json/json.mjs +687 -0
  118. package/dist/json/json.mjs.map +1 -0
  119. package/dist/number/branded-types/finite-number.d.mts +291 -0
  120. package/dist/number/branded-types/finite-number.d.mts.map +1 -0
  121. package/dist/number/branded-types/finite-number.mjs +296 -0
  122. package/dist/number/branded-types/finite-number.mjs.map +1 -0
  123. package/dist/number/branded-types/index.d.mts +27 -0
  124. package/dist/number/branded-types/index.d.mts.map +1 -0
  125. package/dist/number/branded-types/index.mjs +27 -0
  126. package/dist/number/branded-types/index.mjs.map +1 -0
  127. package/dist/number/branded-types/int.d.mts +242 -0
  128. package/dist/number/branded-types/int.d.mts.map +1 -0
  129. package/dist/number/branded-types/int.mjs +239 -0
  130. package/dist/number/branded-types/int.mjs.map +1 -0
  131. package/dist/number/branded-types/int16.d.mts +162 -0
  132. package/dist/number/branded-types/int16.d.mts.map +1 -0
  133. package/dist/number/branded-types/int16.mjs +141 -0
  134. package/dist/number/branded-types/int16.mjs.map +1 -0
  135. package/dist/number/branded-types/int32.d.mts +155 -0
  136. package/dist/number/branded-types/int32.d.mts.map +1 -0
  137. package/dist/number/branded-types/int32.mjs +142 -0
  138. package/dist/number/branded-types/int32.mjs.map +1 -0
  139. package/dist/number/branded-types/non-negative-finite-number.d.mts +165 -0
  140. package/dist/number/branded-types/non-negative-finite-number.d.mts.map +1 -0
  141. package/dist/number/branded-types/non-negative-finite-number.mjs +160 -0
  142. package/dist/number/branded-types/non-negative-finite-number.mjs.map +1 -0
  143. package/dist/number/branded-types/non-negative-int16.d.mts +160 -0
  144. package/dist/number/branded-types/non-negative-int16.d.mts.map +1 -0
  145. package/dist/number/branded-types/non-negative-int16.mjs +138 -0
  146. package/dist/number/branded-types/non-negative-int16.mjs.map +1 -0
  147. package/dist/number/branded-types/non-negative-int32.d.mts +156 -0
  148. package/dist/number/branded-types/non-negative-int32.d.mts.map +1 -0
  149. package/dist/number/branded-types/non-negative-int32.mjs +138 -0
  150. package/dist/number/branded-types/non-negative-int32.mjs.map +1 -0
  151. package/dist/number/branded-types/non-zero-finite-number.d.mts +154 -0
  152. package/dist/number/branded-types/non-zero-finite-number.d.mts.map +1 -0
  153. package/dist/number/branded-types/non-zero-finite-number.mjs +160 -0
  154. package/dist/number/branded-types/non-zero-finite-number.mjs.map +1 -0
  155. package/dist/number/branded-types/non-zero-int.d.mts +131 -0
  156. package/dist/number/branded-types/non-zero-int.d.mts.map +1 -0
  157. package/dist/number/branded-types/non-zero-int.mjs +128 -0
  158. package/dist/number/branded-types/non-zero-int.mjs.map +1 -0
  159. package/dist/number/branded-types/non-zero-int16.d.mts +166 -0
  160. package/dist/number/branded-types/non-zero-int16.d.mts.map +1 -0
  161. package/dist/number/branded-types/non-zero-int16.mjs +145 -0
  162. package/dist/number/branded-types/non-zero-int16.mjs.map +1 -0
  163. package/dist/number/branded-types/non-zero-int32.d.mts +158 -0
  164. package/dist/number/branded-types/non-zero-int32.d.mts.map +1 -0
  165. package/dist/number/branded-types/non-zero-int32.mjs +145 -0
  166. package/dist/number/branded-types/non-zero-int32.mjs.map +1 -0
  167. package/dist/number/branded-types/non-zero-safe-int.d.mts +148 -0
  168. package/dist/number/branded-types/non-zero-safe-int.d.mts.map +1 -0
  169. package/dist/number/branded-types/non-zero-safe-int.mjs +145 -0
  170. package/dist/number/branded-types/non-zero-safe-int.mjs.map +1 -0
  171. package/dist/number/branded-types/non-zero-uint16.d.mts +160 -0
  172. package/dist/number/branded-types/non-zero-uint16.d.mts.map +1 -0
  173. package/dist/number/branded-types/non-zero-uint16.mjs +140 -0
  174. package/dist/number/branded-types/non-zero-uint16.mjs.map +1 -0
  175. package/dist/number/branded-types/non-zero-uint32.d.mts +156 -0
  176. package/dist/number/branded-types/non-zero-uint32.d.mts.map +1 -0
  177. package/dist/number/branded-types/non-zero-uint32.mjs +140 -0
  178. package/dist/number/branded-types/non-zero-uint32.mjs.map +1 -0
  179. package/dist/number/branded-types/positive-finite-number.d.mts +171 -0
  180. package/dist/number/branded-types/positive-finite-number.d.mts.map +1 -0
  181. package/dist/number/branded-types/positive-finite-number.mjs +165 -0
  182. package/dist/number/branded-types/positive-finite-number.mjs.map +1 -0
  183. package/dist/number/branded-types/positive-int.d.mts +270 -0
  184. package/dist/number/branded-types/positive-int.d.mts.map +1 -0
  185. package/dist/number/branded-types/positive-int.mjs +257 -0
  186. package/dist/number/branded-types/positive-int.mjs.map +1 -0
  187. package/dist/number/branded-types/positive-int16.d.mts +162 -0
  188. package/dist/number/branded-types/positive-int16.d.mts.map +1 -0
  189. package/dist/number/branded-types/positive-int16.mjs +139 -0
  190. package/dist/number/branded-types/positive-int16.mjs.map +1 -0
  191. package/dist/number/branded-types/positive-int32.d.mts +158 -0
  192. package/dist/number/branded-types/positive-int32.d.mts.map +1 -0
  193. package/dist/number/branded-types/positive-int32.mjs +139 -0
  194. package/dist/number/branded-types/positive-int32.mjs.map +1 -0
  195. package/dist/number/branded-types/positive-safe-int.d.mts +152 -0
  196. package/dist/number/branded-types/positive-safe-int.d.mts.map +1 -0
  197. package/dist/number/branded-types/positive-safe-int.mjs +138 -0
  198. package/dist/number/branded-types/positive-safe-int.mjs.map +1 -0
  199. package/dist/number/branded-types/positive-uint16.d.mts +160 -0
  200. package/dist/number/branded-types/positive-uint16.d.mts.map +1 -0
  201. package/dist/number/branded-types/positive-uint16.mjs +139 -0
  202. package/dist/number/branded-types/positive-uint16.mjs.map +1 -0
  203. package/dist/number/branded-types/positive-uint32.d.mts +156 -0
  204. package/dist/number/branded-types/positive-uint32.d.mts.map +1 -0
  205. package/dist/number/branded-types/positive-uint32.mjs +139 -0
  206. package/dist/number/branded-types/positive-uint32.mjs.map +1 -0
  207. package/dist/number/branded-types/safe-int.d.mts +243 -0
  208. package/dist/number/branded-types/safe-int.d.mts.map +1 -0
  209. package/dist/number/branded-types/safe-int.mjs +240 -0
  210. package/dist/number/branded-types/safe-int.mjs.map +1 -0
  211. package/dist/number/branded-types/safe-uint.d.mts +151 -0
  212. package/dist/number/branded-types/safe-uint.d.mts.map +1 -0
  213. package/dist/number/branded-types/safe-uint.mjs +138 -0
  214. package/dist/number/branded-types/safe-uint.mjs.map +1 -0
  215. package/dist/number/branded-types/uint.d.mts +144 -0
  216. package/dist/number/branded-types/uint.d.mts.map +1 -0
  217. package/dist/number/branded-types/uint.mjs +132 -0
  218. package/dist/number/branded-types/uint.mjs.map +1 -0
  219. package/dist/number/branded-types/uint16.d.mts +157 -0
  220. package/dist/number/branded-types/uint16.d.mts.map +1 -0
  221. package/dist/number/branded-types/uint16.mjs +137 -0
  222. package/dist/number/branded-types/uint16.mjs.map +1 -0
  223. package/dist/number/branded-types/uint32.d.mts +185 -0
  224. package/dist/number/branded-types/uint32.d.mts.map +1 -0
  225. package/dist/number/branded-types/uint32.mjs +169 -0
  226. package/dist/number/branded-types/uint32.mjs.map +1 -0
  227. package/dist/number/enum/index.d.mts +3 -0
  228. package/dist/number/enum/index.d.mts.map +1 -0
  229. package/dist/number/enum/index.mjs +3 -0
  230. package/dist/number/enum/index.mjs.map +1 -0
  231. package/dist/number/enum/int8.d.mts +202 -0
  232. package/dist/number/enum/int8.d.mts.map +1 -0
  233. package/dist/number/enum/int8.mjs +296 -0
  234. package/dist/number/enum/int8.mjs.map +1 -0
  235. package/dist/number/enum/uint8.d.mts +128 -0
  236. package/dist/number/enum/uint8.d.mts.map +1 -0
  237. package/dist/number/enum/uint8.mjs +251 -0
  238. package/dist/number/enum/uint8.mjs.map +1 -0
  239. package/dist/number/index.d.mts +5 -0
  240. package/dist/number/index.d.mts.map +1 -0
  241. package/dist/number/index.mjs +31 -0
  242. package/dist/number/index.mjs.map +1 -0
  243. package/dist/number/num.d.mts +515 -0
  244. package/dist/number/num.d.mts.map +1 -0
  245. package/dist/number/num.mjs +513 -0
  246. package/dist/number/num.mjs.map +1 -0
  247. package/dist/number/refined-number-utils.d.mts +191 -0
  248. package/dist/number/refined-number-utils.d.mts.map +1 -0
  249. package/dist/number/refined-number-utils.mjs +179 -0
  250. package/dist/number/refined-number-utils.mjs.map +1 -0
  251. package/dist/object/index.d.mts +2 -0
  252. package/dist/object/index.d.mts.map +1 -0
  253. package/dist/object/index.mjs +2 -0
  254. package/dist/object/index.mjs.map +1 -0
  255. package/dist/object/object.d.mts +296 -0
  256. package/dist/object/object.d.mts.map +1 -0
  257. package/dist/object/object.mjs +295 -0
  258. package/dist/object/object.mjs.map +1 -0
  259. package/dist/others/cast-mutable.d.mts +110 -0
  260. package/dist/others/cast-mutable.d.mts.map +1 -0
  261. package/dist/others/cast-mutable.mjs +114 -0
  262. package/dist/others/cast-mutable.mjs.map +1 -0
  263. package/dist/others/cast-readonly.d.mts +189 -0
  264. package/dist/others/cast-readonly.d.mts.map +1 -0
  265. package/dist/others/cast-readonly.mjs +193 -0
  266. package/dist/others/cast-readonly.mjs.map +1 -0
  267. package/dist/others/if-then.d.mts +98 -0
  268. package/dist/others/if-then.d.mts.map +1 -0
  269. package/dist/others/if-then.mjs +100 -0
  270. package/dist/others/if-then.mjs.map +1 -0
  271. package/dist/others/index.d.mts +8 -0
  272. package/dist/others/index.d.mts.map +1 -0
  273. package/dist/others/index.mjs +8 -0
  274. package/dist/others/index.mjs.map +1 -0
  275. package/dist/others/map-nullable.d.mts +151 -0
  276. package/dist/others/map-nullable.d.mts.map +1 -0
  277. package/dist/others/map-nullable.mjs +159 -0
  278. package/dist/others/map-nullable.mjs.map +1 -0
  279. package/dist/others/memoize-function.d.mts +173 -0
  280. package/dist/others/memoize-function.d.mts.map +1 -0
  281. package/dist/others/memoize-function.mjs +189 -0
  282. package/dist/others/memoize-function.mjs.map +1 -0
  283. package/dist/others/tuple.d.mts +159 -0
  284. package/dist/others/tuple.d.mts.map +1 -0
  285. package/dist/others/tuple.mjs +161 -0
  286. package/dist/others/tuple.mjs.map +1 -0
  287. package/dist/others/unknown-to-string.d.mts +180 -0
  288. package/dist/others/unknown-to-string.d.mts.map +1 -0
  289. package/dist/others/unknown-to-string.mjs +211 -0
  290. package/dist/others/unknown-to-string.mjs.map +1 -0
  291. package/dist/tsconfig.json +1 -0
  292. package/package.json +16 -14
@@ -0,0 +1,296 @@
1
+ /**
2
+ * A collection of type-safe object utility functions providing functional programming patterns
3
+ * for object manipulation, including pick, omit, shallow equality checks, and more.
4
+ *
5
+ * All functions maintain TypeScript type safety and support both direct and curried usage patterns
6
+ * for better composition with pipe operations.
7
+ */
8
+ export declare namespace Obj {
9
+ /**
10
+ * Performs a shallow equality check on two records using a configurable equality function.
11
+ * Verifies that both records have the same number of entries and that for every key in the first record,
12
+ * the corresponding value passes the equality test with the value in the second record.
13
+ *
14
+ * @param a - The first record to compare
15
+ * @param b - The second record to compare
16
+ * @param eq - Optional equality function (defaults to Object.is for strict equality)
17
+ * @returns `true` if the records are shallowly equal according to the equality function, `false` otherwise
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * // Basic usage with default Object.is equality
22
+ * Obj.shallowEq({ x: 1, y: 2 }, { x: 1, y: 2 }); // true
23
+ * Obj.shallowEq({ x: 1 }, { x: 1, y: 2 }); // false (different number of keys)
24
+ * Obj.shallowEq({ x: 1 }, { x: 2 }); // false (different values)
25
+ * Obj.shallowEq({}, {}); // true (both empty)
26
+ *
27
+ * // String comparisons
28
+ * Obj.shallowEq({ a: "hello" }, { a: "hello" }); // true
29
+ * Obj.shallowEq({ a: "hello" }, { a: "world" }); // false
30
+ *
31
+ * // Using custom equality function
32
+ * const caseInsensitiveEq = (a: unknown, b: unknown) =>
33
+ * typeof a === 'string' && typeof b === 'string'
34
+ * ? a.toLowerCase() === b.toLowerCase()
35
+ * : a === b;
36
+ *
37
+ * Obj.shallowEq({ name: "ALICE" }, { name: "alice" }, caseInsensitiveEq); // true
38
+ *
39
+ * // Handling special values
40
+ * Obj.shallowEq({ x: NaN }, { x: NaN }); // true (Object.is treats NaN === NaN)
41
+ * Obj.shallowEq({ x: +0 }, { x: -0 }); // false (Object.is distinguishes +0 and -0)
42
+ * ```
43
+ */
44
+ export const shallowEq: (a: UnknownRecord, b: UnknownRecord, eq?: (x: unknown, y: unknown) => boolean) => boolean;
45
+ /**
46
+ * Creates a new record that contains only the specified keys from the source record.
47
+ * This function supports both direct usage and curried form for functional composition.
48
+ *
49
+ * **Type Safety**: Only keys that exist in the source record type are allowed,
50
+ * preventing runtime errors from accessing non-existent properties.
51
+ *
52
+ * @template R - The type of the input record
53
+ * @template Keys - The readonly array type of keys to pick from the record
54
+ *
55
+ * @param record - The source record to pick properties from
56
+ * @param keys - A readonly array of keys to include in the result
57
+ * @returns A new record containing only the specified keys and their values
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * // Direct usage
62
+ * const original = { a: 1, b: 2, c: 3, d: 4 };
63
+ * Obj.pick(original, ['a', 'c']); // { a: 1, c: 3 }
64
+ * Obj.pick(original, ['b']); // { b: 2 }
65
+ * Obj.pick(original, []); // {} (empty result)
66
+ *
67
+ * // Real-world example with user data
68
+ * const user = {
69
+ * id: 1,
70
+ * name: "Alice",
71
+ * email: "alice@example.com",
72
+ * password: "secret123",
73
+ * age: 30
74
+ * };
75
+ *
76
+ * // Extract public user information
77
+ * const publicUser = Obj.pick(user, ['id', 'name', 'email']);
78
+ * // Result: { id: 1, name: "Alice", email: "alice@example.com" }
79
+ *
80
+ * // Curried usage for functional composition
81
+ * const pickIdAndName = Obj.pick(['id', 'name'] as const);
82
+ * const users = [user, { id: 2, name: "Bob", email: "bob@example.com", age: 25 }];
83
+ * const publicUsers = users.map(pickIdAndName);
84
+ * // Result: [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }]
85
+ *
86
+ * // Using with pipe for data transformation
87
+ * import { pipe } from '../functional/pipe.mjs';
88
+ * const result = pipe(user)
89
+ * .map(Obj.pick(['id', 'name']))
90
+ * .map(u => ({ ...u, displayName: u.name.toUpperCase() }))
91
+ * .value;
92
+ * // Result: { id: 1, name: "Alice", displayName: "ALICE" }
93
+ *
94
+ * // Type safety prevents invalid keys
95
+ * // Obj.pick(user, ['invalidKey']); // ❌ TypeScript error
96
+ * // Obj.pick(user, ['id', 'nonExistentField']); // ❌ TypeScript error
97
+ *
98
+ * // Partial key selection (when some keys might not exist)
99
+ * const partialUser = { id: 1, name: "Alice" } as const;
100
+ * const pickVisible = Obj.pick(['name', 'age']); // age might not exist
101
+ * const visible = pickVisible(partialUser); // { name: "Alice" } (age omitted)
102
+ * ```
103
+ */
104
+ export const pick: PickFnOverload;
105
+ type PickFnOverload = {
106
+ <const R extends UnknownRecord, const Keys extends readonly (keyof R)[]>(record: R, keys: Keys): Pick<R, ArrayElement<Keys>>;
107
+ <const Keys extends readonly PropertyKey[]>(keys: Keys): <const R extends UnknownRecord>(record: R) => RelaxedPick<R, ArrayElement<Keys>>;
108
+ };
109
+ /**
110
+ * Creates a new record that excludes the specified keys from the source record.
111
+ * This function supports both direct usage and curried form for functional composition.
112
+ *
113
+ * **Type Safety**: Only keys that exist in the source record type are allowed,
114
+ * and the return type precisely reflects which properties remain after omission.
115
+ *
116
+ * @template R - The type of the input record
117
+ * @template Keys - The readonly array type of keys to omit from the record
118
+ *
119
+ * @param record - The source record to omit properties from
120
+ * @param keys - A readonly array of keys to exclude from the result
121
+ * @returns A new record containing all properties except the specified keys
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * // Direct usage
126
+ * const original = { a: 1, b: 2, c: 3, d: 4 };
127
+ * Obj.omit(original, ['a', 'c']); // { b: 2, d: 4 }
128
+ * Obj.omit(original, ['b']); // { a: 1, c: 3, d: 4 }
129
+ * Obj.omit(original, []); // { a: 1, b: 2, c: 3, d: 4 } (no keys omitted)
130
+ *
131
+ * // Real-world example: removing sensitive data
132
+ * const user = {
133
+ * id: 1,
134
+ * name: "Alice",
135
+ * email: "alice@example.com",
136
+ * password: "secret123",
137
+ * apiKey: "abc-def-ghi",
138
+ * lastLogin: new Date()
139
+ * };
140
+ *
141
+ * // Create safe user object for client-side
142
+ * const safeUser = Obj.omit(user, ['password', 'apiKey']);
143
+ * // Result: { id: 1, name: "Alice", email: "alice@example.com", lastLogin: Date }
144
+ *
145
+ * // Curried usage for data processing pipelines
146
+ * const removeSensitive = Obj.omit(['password', 'apiKey', 'ssn'] as const);
147
+ * const users = [user]; // array of user objects
148
+ * const safeUsers = users.map(removeSensitive);
149
+ *
150
+ * // Using with pipe for complex transformations
151
+ * import { pipe } from '../functional/pipe.mjs';
152
+ * const publicProfile = pipe(user)
153
+ * .map(Obj.omit(['password', 'apiKey']))
154
+ * .map(u => ({ ...u, displayName: u.name.toUpperCase() }))
155
+ * .value;
156
+ * // Result: { id: 1, name: "Alice", email: "...", lastLogin: Date, displayName: "ALICE" }
157
+ *
158
+ * // Database queries: exclude computed fields
159
+ * const dbUser = {
160
+ * id: 1,
161
+ * name: "Alice",
162
+ * email: "alice@example.com",
163
+ * createdAt: new Date(),
164
+ * updatedAt: new Date(),
165
+ * fullName: "Alice Johnson", // computed field
166
+ * isActive: true // computed field
167
+ * };
168
+ *
169
+ * const storableData = Obj.omit(dbUser, ['fullName', 'isActive']);
170
+ * // Only data that should be persisted to database
171
+ *
172
+ * // Type safety prevents invalid operations
173
+ * // Obj.omit(user, ['invalidKey']); // ❌ TypeScript error
174
+ * // Obj.omit(user, ['id', 'nonExistentField']); // ❌ TypeScript error
175
+ *
176
+ * // Handling partial omission (when some keys might not exist)
177
+ * const partialUser = { id: 1, name: "Alice", password: "secret" } as const;
178
+ * const omitCredentials = Obj.omit(['password', 'apiKey']); // apiKey might not exist
179
+ * const cleaned = omitCredentials(partialUser); // { id: 1, name: "Alice" }
180
+ * ```
181
+ */
182
+ export const omit: OmitFnOverload;
183
+ type OmitFnOverload = {
184
+ <const R extends UnknownRecord, const Keys extends readonly (keyof R)[]>(record: R, keys: Keys): Omit<R, ArrayElement<Keys>>;
185
+ <const Keys extends readonly PropertyKey[]>(keys: Keys): <const R extends UnknownRecord>(record: R) => Omit<R, ArrayElement<Keys>>;
186
+ };
187
+ /**
188
+ * Creates an object from an array of key-value pairs with precise TypeScript typing.
189
+ * This is a type-safe wrapper around `Object.fromEntries` that provides better type inference
190
+ * and compile-time guarantees about the resulting object structure.
191
+ *
192
+ * **Type Behavior**:
193
+ * - When entries is a fixed-length tuple, the exact object type is inferred
194
+ * - When entries has dynamic length with union key types, `Partial` is applied to prevent
195
+ * incorrect assumptions about which keys will be present
196
+ *
197
+ * @template Entries - The readonly array type of key-value entry tuples
198
+ * @param entries - An array of readonly key-value entry tuples `[key, value]`
199
+ * @returns An object created from the entries with precise typing
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * // Fixed entries with precise typing
204
+ * const fixedEntries = [
205
+ * ['name', 'Alice'],
206
+ * ['age', 30],
207
+ * ['active', true]
208
+ * ] as const;
209
+ *
210
+ * const user = Obj.fromEntries(fixedEntries);
211
+ * // Type: { readonly name: "Alice"; readonly age: 30; readonly active: true }
212
+ * // Value: { name: "Alice", age: 30, active: true }
213
+ *
214
+ * // Simple coordinate example
215
+ * const coordEntries = [['x', 1], ['y', 3]] as const;
216
+ * const point = Obj.fromEntries(coordEntries);
217
+ * // Type: { readonly x: 1; readonly y: 3 }
218
+ * // Value: { x: 1, y: 3 }
219
+ *
220
+ * // Dynamic entries with union keys
221
+ * const dynamicEntries: Array<['name' | 'email', string]> = [
222
+ * ['name', 'Alice']
223
+ * // email might or might not be present
224
+ * ];
225
+ * const partialUser = Obj.fromEntries(dynamicEntries);
226
+ * // Type: Partial<{ name: string; email: string }>
227
+ * // This prevents assuming both 'name' and 'email' are always present
228
+ *
229
+ * // Creating configuration objects
230
+ * const configEntries = [
231
+ * ['apiUrl', 'https://api.example.com'],
232
+ * ['timeout', 5000],
233
+ * ['retries', 3],
234
+ * ['debug', false]
235
+ * ] as const;
236
+ * const config = Obj.fromEntries(configEntries);
237
+ * // Precise types for each configuration value
238
+ *
239
+ * // Converting Maps to objects
240
+ * const settingsMap = new Map([
241
+ * ['theme', 'dark'],
242
+ * ['language', 'en'],
243
+ * ['notifications', true]
244
+ * ] as const);
245
+ * const settings = Obj.fromEntries([...settingsMap]);
246
+ *
247
+ * // Building objects from computed entries
248
+ * const keys = ['a', 'b', 'c'] as const;
249
+ * const values = [1, 2, 3] as const;
250
+ * const computedEntries = keys.map((k, i) => [k, values[i]] as const);
251
+ * const computed = Obj.fromEntries(computedEntries);
252
+ * // Type reflects the specific key-value associations
253
+ *
254
+ * // Error handling with validation
255
+ * function createUserFromEntries(entries: ReadonlyArray<readonly [string, unknown]>) {
256
+ * const user = Obj.fromEntries(entries);
257
+ * // Type is Partial<Record<string, unknown>> - safe for dynamic data
258
+ *
259
+ * if ('name' in user && typeof user.name === 'string') {
260
+ * // Type narrowing works correctly
261
+ * return { name: user.name, ...user };
262
+ * }
263
+ * throw new Error('Invalid user data');
264
+ * }
265
+ * ```
266
+ */
267
+ export const fromEntries: <const Entries extends readonly (readonly [PropertyKey, unknown])[]>(entries: Entries) => IsFixedLengthList<Entries> extends true ? TsVerifiedInternals.EntriesToObject<Entries> : TsVerifiedInternals.PartialIfKeyIsUnion<TsVerifiedInternals.KeysOfEntries<Entries>, Record<TsVerifiedInternals.KeysOfEntries<Entries>, TsVerifiedInternals.ValuesOfEntries<Entries>>>;
268
+ /**
269
+ * @internal
270
+ * Internal type utilities for the Obj module.
271
+ */
272
+ namespace TsVerifiedInternals {
273
+ type RecursionLimit = 20;
274
+ /**
275
+ * - `[['x', 1], ['y', 3]]` -> `{ x: 1, y: 3 }`
276
+ */
277
+ type EntriesToObject<Entries extends readonly (readonly [PropertyKey, unknown])[]> = Readonly<EntriesToObjectImpl<{}, Entries>>;
278
+ /** @internal */
279
+ type EntriesToObjectImpl<R, Entries extends readonly (readonly [PropertyKey, unknown])[]> = TypeEq<Entries['length'], 0> extends true ? R : EntriesToObjectImpl<R & Readonly<Record<Entries[0][0], Entries[0][1]>>, List.Tail<Entries>>;
280
+ /**
281
+ * - `['x' | 'y' | 'z', number][]]` -> `'x' | 'y' | 'z'`
282
+ * - `[['a' | 'b' | 'c', number], ...['x' | 'y' | 'z', number][]]` -> `'a' | 'b' |
283
+ * 'c' | 'x' | 'y' | 'z'`
284
+ *
285
+ * @note To handle the second example above, recursion needs to be performed on infinite-length Entries,
286
+ * but since the timing to stop cannot be determined, a recursion limit is set.
287
+ */
288
+ type KeysOfEntries<Entries extends readonly (readonly [PropertyKey, unknown])[]> = KeysOfEntriesImpl<never, Entries, RecursionLimit>;
289
+ type KeysOfEntriesImpl<K, Entries extends readonly (readonly [PropertyKey, unknown])[], RemainingNumRecursions extends number> = TypeEq<RemainingNumRecursions, 0> extends true ? K : TypeEq<Entries['length'], 0> extends true ? K : KeysOfEntriesImpl<K | Entries[0][0], List.Tail<Entries>, Decrement<RemainingNumRecursions>>;
290
+ type ValuesOfEntries<Entries extends readonly (readonly [PropertyKey, unknown])[]> = ValuesOfEntriesImpl<never, Entries, RecursionLimit>;
291
+ type ValuesOfEntriesImpl<K, Entries extends readonly (readonly [PropertyKey, unknown])[], RemainingNumRecursions extends number> = TypeEq<RemainingNumRecursions, 0> extends true ? K : TypeEq<Entries['length'], 0> extends true ? K : ValuesOfEntriesImpl<K | Entries[0][1], List.Tail<Entries>, Decrement<RemainingNumRecursions>>;
292
+ type PartialIfKeyIsUnion<K, T> = IsUnion<K> extends true ? Partial<T> : T;
293
+ }
294
+ export {};
295
+ }
296
+ //# sourceMappingURL=object.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object.d.mts","sourceRoot":"","sources":["../../src/object/object.mts"],"names":[],"mappings":"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"}
@@ -0,0 +1,295 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-type-assertion */
2
+ /**
3
+ * A collection of type-safe object utility functions providing functional programming patterns
4
+ * for object manipulation, including pick, omit, shallow equality checks, and more.
5
+ *
6
+ * All functions maintain TypeScript type safety and support both direct and curried usage patterns
7
+ * for better composition with pipe operations.
8
+ */
9
+ var Obj;
10
+ (function (Obj) {
11
+ /**
12
+ * Performs a shallow equality check on two records using a configurable equality function.
13
+ * Verifies that both records have the same number of entries and that for every key in the first record,
14
+ * the corresponding value passes the equality test with the value in the second record.
15
+ *
16
+ * @param a - The first record to compare
17
+ * @param b - The second record to compare
18
+ * @param eq - Optional equality function (defaults to Object.is for strict equality)
19
+ * @returns `true` if the records are shallowly equal according to the equality function, `false` otherwise
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // Basic usage with default Object.is equality
24
+ * Obj.shallowEq({ x: 1, y: 2 }, { x: 1, y: 2 }); // true
25
+ * Obj.shallowEq({ x: 1 }, { x: 1, y: 2 }); // false (different number of keys)
26
+ * Obj.shallowEq({ x: 1 }, { x: 2 }); // false (different values)
27
+ * Obj.shallowEq({}, {}); // true (both empty)
28
+ *
29
+ * // String comparisons
30
+ * Obj.shallowEq({ a: "hello" }, { a: "hello" }); // true
31
+ * Obj.shallowEq({ a: "hello" }, { a: "world" }); // false
32
+ *
33
+ * // Using custom equality function
34
+ * const caseInsensitiveEq = (a: unknown, b: unknown) =>
35
+ * typeof a === 'string' && typeof b === 'string'
36
+ * ? a.toLowerCase() === b.toLowerCase()
37
+ * : a === b;
38
+ *
39
+ * Obj.shallowEq({ name: "ALICE" }, { name: "alice" }, caseInsensitiveEq); // true
40
+ *
41
+ * // Handling special values
42
+ * Obj.shallowEq({ x: NaN }, { x: NaN }); // true (Object.is treats NaN === NaN)
43
+ * Obj.shallowEq({ x: +0 }, { x: -0 }); // false (Object.is distinguishes +0 and -0)
44
+ * ```
45
+ */
46
+ Obj.shallowEq = (a, b, eq = Object.is) => {
47
+ const aEntries = Object.entries(a);
48
+ const bEntries = Object.entries(b);
49
+ if (aEntries.length !== bEntries.length)
50
+ return false;
51
+ return aEntries.every(([k, v]) => eq(b[k], v));
52
+ };
53
+ /**
54
+ * Creates a new record that contains only the specified keys from the source record.
55
+ * This function supports both direct usage and curried form for functional composition.
56
+ *
57
+ * **Type Safety**: Only keys that exist in the source record type are allowed,
58
+ * preventing runtime errors from accessing non-existent properties.
59
+ *
60
+ * @template R - The type of the input record
61
+ * @template Keys - The readonly array type of keys to pick from the record
62
+ *
63
+ * @param record - The source record to pick properties from
64
+ * @param keys - A readonly array of keys to include in the result
65
+ * @returns A new record containing only the specified keys and their values
66
+ *
67
+ * @example
68
+ * ```typescript
69
+ * // Direct usage
70
+ * const original = { a: 1, b: 2, c: 3, d: 4 };
71
+ * Obj.pick(original, ['a', 'c']); // { a: 1, c: 3 }
72
+ * Obj.pick(original, ['b']); // { b: 2 }
73
+ * Obj.pick(original, []); // {} (empty result)
74
+ *
75
+ * // Real-world example with user data
76
+ * const user = {
77
+ * id: 1,
78
+ * name: "Alice",
79
+ * email: "alice@example.com",
80
+ * password: "secret123",
81
+ * age: 30
82
+ * };
83
+ *
84
+ * // Extract public user information
85
+ * const publicUser = Obj.pick(user, ['id', 'name', 'email']);
86
+ * // Result: { id: 1, name: "Alice", email: "alice@example.com" }
87
+ *
88
+ * // Curried usage for functional composition
89
+ * const pickIdAndName = Obj.pick(['id', 'name'] as const);
90
+ * const users = [user, { id: 2, name: "Bob", email: "bob@example.com", age: 25 }];
91
+ * const publicUsers = users.map(pickIdAndName);
92
+ * // Result: [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }]
93
+ *
94
+ * // Using with pipe for data transformation
95
+ * import { pipe } from '../functional/pipe.mjs';
96
+ * const result = pipe(user)
97
+ * .map(Obj.pick(['id', 'name']))
98
+ * .map(u => ({ ...u, displayName: u.name.toUpperCase() }))
99
+ * .value;
100
+ * // Result: { id: 1, name: "Alice", displayName: "ALICE" }
101
+ *
102
+ * // Type safety prevents invalid keys
103
+ * // Obj.pick(user, ['invalidKey']); // ❌ TypeScript error
104
+ * // Obj.pick(user, ['id', 'nonExistentField']); // ❌ TypeScript error
105
+ *
106
+ * // Partial key selection (when some keys might not exist)
107
+ * const partialUser = { id: 1, name: "Alice" } as const;
108
+ * const pickVisible = Obj.pick(['name', 'age']); // age might not exist
109
+ * const visible = pickVisible(partialUser); // { name: "Alice" } (age omitted)
110
+ * ```
111
+ */
112
+ Obj.pick = ((...args) => {
113
+ switch (args.length) {
114
+ case 2: {
115
+ const [record, keys] = args;
116
+ const keysSet = new Set(keys);
117
+ return Object.fromEntries(Object.entries(record).filter(([k, _v]) => keysSet.has(k)));
118
+ }
119
+ case 1: {
120
+ const [keys] = args;
121
+ return (record) => Obj.pick(record, keys);
122
+ }
123
+ }
124
+ });
125
+ /**
126
+ * Creates a new record that excludes the specified keys from the source record.
127
+ * This function supports both direct usage and curried form for functional composition.
128
+ *
129
+ * **Type Safety**: Only keys that exist in the source record type are allowed,
130
+ * and the return type precisely reflects which properties remain after omission.
131
+ *
132
+ * @template R - The type of the input record
133
+ * @template Keys - The readonly array type of keys to omit from the record
134
+ *
135
+ * @param record - The source record to omit properties from
136
+ * @param keys - A readonly array of keys to exclude from the result
137
+ * @returns A new record containing all properties except the specified keys
138
+ *
139
+ * @example
140
+ * ```typescript
141
+ * // Direct usage
142
+ * const original = { a: 1, b: 2, c: 3, d: 4 };
143
+ * Obj.omit(original, ['a', 'c']); // { b: 2, d: 4 }
144
+ * Obj.omit(original, ['b']); // { a: 1, c: 3, d: 4 }
145
+ * Obj.omit(original, []); // { a: 1, b: 2, c: 3, d: 4 } (no keys omitted)
146
+ *
147
+ * // Real-world example: removing sensitive data
148
+ * const user = {
149
+ * id: 1,
150
+ * name: "Alice",
151
+ * email: "alice@example.com",
152
+ * password: "secret123",
153
+ * apiKey: "abc-def-ghi",
154
+ * lastLogin: new Date()
155
+ * };
156
+ *
157
+ * // Create safe user object for client-side
158
+ * const safeUser = Obj.omit(user, ['password', 'apiKey']);
159
+ * // Result: { id: 1, name: "Alice", email: "alice@example.com", lastLogin: Date }
160
+ *
161
+ * // Curried usage for data processing pipelines
162
+ * const removeSensitive = Obj.omit(['password', 'apiKey', 'ssn'] as const);
163
+ * const users = [user]; // array of user objects
164
+ * const safeUsers = users.map(removeSensitive);
165
+ *
166
+ * // Using with pipe for complex transformations
167
+ * import { pipe } from '../functional/pipe.mjs';
168
+ * const publicProfile = pipe(user)
169
+ * .map(Obj.omit(['password', 'apiKey']))
170
+ * .map(u => ({ ...u, displayName: u.name.toUpperCase() }))
171
+ * .value;
172
+ * // Result: { id: 1, name: "Alice", email: "...", lastLogin: Date, displayName: "ALICE" }
173
+ *
174
+ * // Database queries: exclude computed fields
175
+ * const dbUser = {
176
+ * id: 1,
177
+ * name: "Alice",
178
+ * email: "alice@example.com",
179
+ * createdAt: new Date(),
180
+ * updatedAt: new Date(),
181
+ * fullName: "Alice Johnson", // computed field
182
+ * isActive: true // computed field
183
+ * };
184
+ *
185
+ * const storableData = Obj.omit(dbUser, ['fullName', 'isActive']);
186
+ * // Only data that should be persisted to database
187
+ *
188
+ * // Type safety prevents invalid operations
189
+ * // Obj.omit(user, ['invalidKey']); // ❌ TypeScript error
190
+ * // Obj.omit(user, ['id', 'nonExistentField']); // ❌ TypeScript error
191
+ *
192
+ * // Handling partial omission (when some keys might not exist)
193
+ * const partialUser = { id: 1, name: "Alice", password: "secret" } as const;
194
+ * const omitCredentials = Obj.omit(['password', 'apiKey']); // apiKey might not exist
195
+ * const cleaned = omitCredentials(partialUser); // { id: 1, name: "Alice" }
196
+ * ```
197
+ */
198
+ Obj.omit = ((...args) => {
199
+ switch (args.length) {
200
+ case 2: {
201
+ const [record, keys] = args;
202
+ const keysSet = new Set(keys);
203
+ return Object.fromEntries(Object.entries(record).filter(([k, _v]) => !keysSet.has(k)));
204
+ }
205
+ case 1: {
206
+ const [keys] = args;
207
+ return (record) => Obj.omit(record, keys);
208
+ }
209
+ }
210
+ });
211
+ /**
212
+ * Creates an object from an array of key-value pairs with precise TypeScript typing.
213
+ * This is a type-safe wrapper around `Object.fromEntries` that provides better type inference
214
+ * and compile-time guarantees about the resulting object structure.
215
+ *
216
+ * **Type Behavior**:
217
+ * - When entries is a fixed-length tuple, the exact object type is inferred
218
+ * - When entries has dynamic length with union key types, `Partial` is applied to prevent
219
+ * incorrect assumptions about which keys will be present
220
+ *
221
+ * @template Entries - The readonly array type of key-value entry tuples
222
+ * @param entries - An array of readonly key-value entry tuples `[key, value]`
223
+ * @returns An object created from the entries with precise typing
224
+ *
225
+ * @example
226
+ * ```typescript
227
+ * // Fixed entries with precise typing
228
+ * const fixedEntries = [
229
+ * ['name', 'Alice'],
230
+ * ['age', 30],
231
+ * ['active', true]
232
+ * ] as const;
233
+ *
234
+ * const user = Obj.fromEntries(fixedEntries);
235
+ * // Type: { readonly name: "Alice"; readonly age: 30; readonly active: true }
236
+ * // Value: { name: "Alice", age: 30, active: true }
237
+ *
238
+ * // Simple coordinate example
239
+ * const coordEntries = [['x', 1], ['y', 3]] as const;
240
+ * const point = Obj.fromEntries(coordEntries);
241
+ * // Type: { readonly x: 1; readonly y: 3 }
242
+ * // Value: { x: 1, y: 3 }
243
+ *
244
+ * // Dynamic entries with union keys
245
+ * const dynamicEntries: Array<['name' | 'email', string]> = [
246
+ * ['name', 'Alice']
247
+ * // email might or might not be present
248
+ * ];
249
+ * const partialUser = Obj.fromEntries(dynamicEntries);
250
+ * // Type: Partial<{ name: string; email: string }>
251
+ * // This prevents assuming both 'name' and 'email' are always present
252
+ *
253
+ * // Creating configuration objects
254
+ * const configEntries = [
255
+ * ['apiUrl', 'https://api.example.com'],
256
+ * ['timeout', 5000],
257
+ * ['retries', 3],
258
+ * ['debug', false]
259
+ * ] as const;
260
+ * const config = Obj.fromEntries(configEntries);
261
+ * // Precise types for each configuration value
262
+ *
263
+ * // Converting Maps to objects
264
+ * const settingsMap = new Map([
265
+ * ['theme', 'dark'],
266
+ * ['language', 'en'],
267
+ * ['notifications', true]
268
+ * ] as const);
269
+ * const settings = Obj.fromEntries([...settingsMap]);
270
+ *
271
+ * // Building objects from computed entries
272
+ * const keys = ['a', 'b', 'c'] as const;
273
+ * const values = [1, 2, 3] as const;
274
+ * const computedEntries = keys.map((k, i) => [k, values[i]] as const);
275
+ * const computed = Obj.fromEntries(computedEntries);
276
+ * // Type reflects the specific key-value associations
277
+ *
278
+ * // Error handling with validation
279
+ * function createUserFromEntries(entries: ReadonlyArray<readonly [string, unknown]>) {
280
+ * const user = Obj.fromEntries(entries);
281
+ * // Type is Partial<Record<string, unknown>> - safe for dynamic data
282
+ *
283
+ * if ('name' in user && typeof user.name === 'string') {
284
+ * // Type narrowing works correctly
285
+ * return { name: user.name, ...user };
286
+ * }
287
+ * throw new Error('Invalid user data');
288
+ * }
289
+ * ```
290
+ */
291
+ Obj.fromEntries = (entries) => Object.fromEntries(entries);
292
+ })(Obj || (Obj = {}));
293
+
294
+ export { Obj };
295
+ //# sourceMappingURL=object.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"object.mjs","sources":["../../src/object/object.mts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;AACA;;;;;;AAMG;AACG,IAAW;AAAjB,CAAA,UAAiB,GAAG,EAAA;AAClB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCG;IACU,GAAA,CAAA,SAAS,GAAG,CACvB,CAAgB,EAChB,CAAgB,EAChB,EAAA,GAA0C,MAAM,CAAC,EAAE,KACxC;QACX,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QAClC,MAAM,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;AAElC,QAAA,IAAI,QAAQ,CAAC,MAAM,KAAK,QAAQ,CAAC,MAAM;AAAE,YAAA,OAAO,KAAK;QAErD,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAChD,KAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DG;AACU,IAAA,GAAA,CAAA,IAAI,IAAoB,CAInC,GAAG,IAEwC,KAGa;AACxD,QAAA,QAAQ,IAAI,CAAC,MAAM;YACjB,KAAK,CAAC,EAAE;AACN,gBAAA,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,IAAI;AAC3B,gBAAA,MAAM,OAAO,GAAG,IAAI,GAAG,CAAU,IAAI,CAAC;AAEtC,gBAAA,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAClD;;YAGZ,KAAK,CAAC,EAAE;AACN,gBAAA,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI;AACnB,gBAAA,OAAO,CAA2B,MAAU,KAC1C,GAAA,CAAA,IAAI,CAAC,MAAM,EAAE,IAA6B,CAAC;;;AAGnD,KAAC,CAAmB;AAgBpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwEG;AACU,IAAA,GAAA,CAAA,IAAI,IAAoB,CAInC,GAAG,IAEwC,KAGM;AACjD,QAAA,QAAQ,IAAI,CAAC,MAAM;YACjB,KAAK,CAAC,EAAE;AACN,gBAAA,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,IAAI;AAC3B,gBAAA,MAAM,OAAO,GAAG,IAAI,GAAG,CAAU,IAAI,CAAC;AAEtC,gBAAA,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CACnD;;YAGZ,KAAK,CAAC,EAAE;AACN,gBAAA,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI;AACnB,gBAAA,OAAO,CAA2B,MAAU,KAC1C,GAAA,CAAA,IAAI,CAAC,MAAM,EAAE,IAA6B,CAGzC;;;AAGT,KAAC,CAAmB;AAgBpB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+EG;AACU,IAAA,GAAA,CAAA,WAAW,GAAG,CAGzB,OAAgB,KAST,MAAM,CAAC,WAAW,CAAC,OAAO,CAAU;AA8E/C,CAAC,EAtbgB,GAAG,KAAH,GAAG,GAAA,EAAA,CAAA,CAAA;;;;"}