ts-data-forge 14.6.2 → 14.6.4

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 (182) hide show
  1. package/dist/array/impl/array-utils-creation.mjs +103 -103
  2. package/dist/array/impl/array-utils-element-access.mjs +46 -46
  3. package/dist/array/impl/array-utils-iterators.mjs +54 -54
  4. package/dist/array/impl/array-utils-length-bounded-array-cast.mjs +49 -49
  5. package/dist/array/impl/array-utils-length-bounded-array-guard.mjs +40 -40
  6. package/dist/array/impl/array-utils-length-bounded-tuple-cast.mjs +42 -42
  7. package/dist/array/impl/array-utils-length-bounded-tuple-guard.mjs +46 -46
  8. package/dist/array/impl/array-utils-modification.mjs +5 -5
  9. package/dist/array/impl/array-utils-reducing-value.mjs +11 -11
  10. package/dist/array/impl/array-utils-search.mjs +6 -6
  11. package/dist/array/impl/array-utils-set-op.mjs +116 -116
  12. package/dist/array/impl/array-utils-size.mjs +6 -6
  13. package/dist/array/impl/array-utils-slice-clamped.mjs +1 -1
  14. package/dist/array/impl/array-utils-slicing.mjs +56 -56
  15. package/dist/array/impl/array-utils-transformation.mjs +158 -158
  16. package/dist/array/impl/array-utils-validation.mjs +36 -36
  17. package/dist/collections/imap-mapped.mjs +195 -195
  18. package/dist/collections/imap.mjs +143 -143
  19. package/dist/collections/iset-mapped.mjs +320 -320
  20. package/dist/collections/iset.mjs +207 -207
  21. package/dist/collections/queue.mjs +130 -130
  22. package/dist/collections/stack.mjs +125 -125
  23. package/dist/expect-type.mjs +68 -68
  24. package/dist/functional/async-result/impl/async-result-flat-map.mjs +3 -3
  25. package/dist/functional/async-result/impl/async-result-map-err.mjs +2 -2
  26. package/dist/functional/async-result/impl/async-result-map.mjs +2 -2
  27. package/dist/functional/async-result/impl/async-result-unwrap-or.mjs +31 -31
  28. package/dist/functional/optional/impl/optional-expect-to-be.mjs +1 -1
  29. package/dist/functional/optional/impl/optional-filter.mjs +1 -1
  30. package/dist/functional/optional/impl/optional-flat-map.mjs +1 -1
  31. package/dist/functional/optional/impl/optional-from-nullable.mjs +24 -24
  32. package/dist/functional/optional/impl/optional-is-none.mjs +19 -19
  33. package/dist/functional/optional/impl/optional-is-optional.mjs +18 -18
  34. package/dist/functional/optional/impl/optional-is-some.mjs +20 -20
  35. package/dist/functional/optional/impl/optional-map.mjs +2 -2
  36. package/dist/functional/optional/impl/optional-match.mjs +2 -2
  37. package/dist/functional/optional/impl/optional-none.mjs +16 -16
  38. package/dist/functional/optional/impl/optional-or-else.mjs +1 -1
  39. package/dist/functional/optional/impl/optional-some.mjs +19 -19
  40. package/dist/functional/optional/impl/optional-to-nullable.mjs +26 -26
  41. package/dist/functional/optional/impl/optional-unwrap-or.mjs +1 -1
  42. package/dist/functional/optional/impl/optional-unwrap-throw.mjs +28 -28
  43. package/dist/functional/optional/impl/optional-unwrap.mjs +1 -1
  44. package/dist/functional/optional/impl/optional-zip.mjs +32 -32
  45. package/dist/functional/optional/impl/tag.mjs +1 -1
  46. package/dist/functional/pipe.mjs +19 -19
  47. package/dist/functional/result/impl/result-err.mjs +25 -25
  48. package/dist/functional/result/impl/result-expect-to-be.mjs +2 -2
  49. package/dist/functional/result/impl/result-flat-map.mjs +4 -4
  50. package/dist/functional/result/impl/result-fold.mjs +4 -4
  51. package/dist/functional/result/impl/result-from-optional.mjs +2 -2
  52. package/dist/functional/result/impl/result-from-promise.mjs +34 -34
  53. package/dist/functional/result/impl/result-from-throwable.mjs +29 -29
  54. package/dist/functional/result/impl/result-is-err.mjs +19 -19
  55. package/dist/functional/result/impl/result-is-ok.mjs +19 -19
  56. package/dist/functional/result/impl/result-is-result.mjs +19 -19
  57. package/dist/functional/result/impl/result-map-err.mjs +4 -4
  58. package/dist/functional/result/impl/result-map.mjs +4 -4
  59. package/dist/functional/result/impl/result-match.mjs +3 -3
  60. package/dist/functional/result/impl/result-ok.mjs +25 -25
  61. package/dist/functional/result/impl/result-or-else.mjs +2 -2
  62. package/dist/functional/result/impl/result-safe-try.mjs +15 -15
  63. package/dist/functional/result/impl/result-safe-unwrap.mjs +33 -33
  64. package/dist/functional/result/impl/result-swap.mjs +20 -20
  65. package/dist/functional/result/impl/result-to-optional.mjs +27 -27
  66. package/dist/functional/result/impl/result-unwrap-err-or.mjs +2 -2
  67. package/dist/functional/result/impl/result-unwrap-err-throw.mjs +31 -31
  68. package/dist/functional/result/impl/result-unwrap-err.mjs +30 -30
  69. package/dist/functional/result/impl/result-unwrap-ok-or.mjs +2 -2
  70. package/dist/functional/result/impl/result-unwrap-ok.mjs +1 -1
  71. package/dist/functional/result/impl/result-unwrap-throw.mjs +31 -31
  72. package/dist/functional/result/impl/result-zip.mjs +29 -29
  73. package/dist/functional/result/impl/tag.mjs +1 -1
  74. package/dist/functional/ternary-result/impl/tag.mjs +2 -2
  75. package/dist/functional/ternary-result/impl/ternary-result-err.mjs +13 -13
  76. package/dist/functional/ternary-result/impl/ternary-result-flat-map.mjs +4 -4
  77. package/dist/functional/ternary-result/impl/ternary-result-fold.mjs +4 -4
  78. package/dist/functional/ternary-result/impl/ternary-result-from-promise.mjs +18 -18
  79. package/dist/functional/ternary-result/impl/ternary-result-from-throwable.mjs +17 -17
  80. package/dist/functional/ternary-result/impl/ternary-result-is-err.mjs +17 -17
  81. package/dist/functional/ternary-result/impl/ternary-result-is-ok.mjs +19 -19
  82. package/dist/functional/ternary-result/impl/ternary-result-is-ternary-result.mjs +19 -19
  83. package/dist/functional/ternary-result/impl/ternary-result-is-warn.mjs +18 -18
  84. package/dist/functional/ternary-result/impl/ternary-result-map-err.mjs +2 -2
  85. package/dist/functional/ternary-result/impl/ternary-result-map-warn.mjs +3 -3
  86. package/dist/functional/ternary-result/impl/ternary-result-map.mjs +4 -4
  87. package/dist/functional/ternary-result/impl/ternary-result-ok.mjs +14 -14
  88. package/dist/functional/ternary-result/impl/ternary-result-to-optional.mjs +19 -19
  89. package/dist/functional/ternary-result/impl/ternary-result-unwrap-err-throw.mjs +19 -19
  90. package/dist/functional/ternary-result/impl/ternary-result-unwrap-err.mjs +17 -17
  91. package/dist/functional/ternary-result/impl/ternary-result-unwrap-ok.mjs +1 -1
  92. package/dist/functional/ternary-result/impl/ternary-result-unwrap-throw.mjs +20 -20
  93. package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn-throw.mjs +18 -18
  94. package/dist/functional/ternary-result/impl/ternary-result-unwrap-warn.mjs +17 -17
  95. package/dist/functional/ternary-result/impl/ternary-result-warn.mjs +16 -16
  96. package/dist/functional/ternary-result/impl/ternary-result-zip.mjs +31 -31
  97. package/dist/functional/ternary-result/impl/variant-name.mjs +1 -1
  98. package/dist/guard/has-key.mjs +41 -41
  99. package/dist/guard/is-non-empty-string.mjs +37 -37
  100. package/dist/guard/is-non-null-object.mjs +34 -34
  101. package/dist/guard/is-primitive.mjs +31 -31
  102. package/dist/guard/is-record.mjs +86 -86
  103. package/dist/guard/is-type.mjs +387 -387
  104. package/dist/guard/key-is-in.mjs +40 -40
  105. package/dist/iterator/range.mjs +1 -1
  106. package/dist/json/json.mjs +289 -289
  107. package/dist/number/branded-types/finite-number.mjs +116 -116
  108. package/dist/number/branded-types/int.mjs +223 -223
  109. package/dist/number/branded-types/int16.mjs +116 -116
  110. package/dist/number/branded-types/int32.mjs +116 -116
  111. package/dist/number/branded-types/negative-finite-number.mjs +126 -126
  112. package/dist/number/branded-types/negative-int.mjs +104 -104
  113. package/dist/number/branded-types/negative-safe-int.mjs +104 -104
  114. package/dist/number/branded-types/non-negative-finite-number.mjs +132 -132
  115. package/dist/number/branded-types/non-negative-int16.mjs +113 -113
  116. package/dist/number/branded-types/non-negative-int32.mjs +113 -113
  117. package/dist/number/branded-types/non-positive-finite-number.mjs +116 -116
  118. package/dist/number/branded-types/non-positive-int.mjs +97 -97
  119. package/dist/number/branded-types/non-positive-safe-int.mjs +98 -98
  120. package/dist/number/branded-types/non-zero-finite-number.mjs +112 -112
  121. package/dist/number/branded-types/non-zero-int.mjs +82 -82
  122. package/dist/number/branded-types/non-zero-int16.mjs +95 -95
  123. package/dist/number/branded-types/non-zero-int32.mjs +95 -95
  124. package/dist/number/branded-types/non-zero-safe-int.mjs +99 -99
  125. package/dist/number/branded-types/non-zero-uint16.mjs +95 -95
  126. package/dist/number/branded-types/non-zero-uint32.mjs +95 -95
  127. package/dist/number/branded-types/positive-finite-number.mjs +134 -134
  128. package/dist/number/branded-types/positive-int.mjs +237 -237
  129. package/dist/number/branded-types/positive-int16.mjs +110 -110
  130. package/dist/number/branded-types/positive-int32.mjs +110 -110
  131. package/dist/number/branded-types/positive-safe-int.mjs +268 -268
  132. package/dist/number/branded-types/positive-uint16.mjs +110 -110
  133. package/dist/number/branded-types/positive-uint32.mjs +110 -110
  134. package/dist/number/branded-types/safe-int.mjs +259 -259
  135. package/dist/number/branded-types/safe-uint.mjs +111 -111
  136. package/dist/number/branded-types/uint.mjs +225 -225
  137. package/dist/number/branded-types/uint16.mjs +108 -108
  138. package/dist/number/branded-types/uint32.mjs +108 -108
  139. package/dist/number/enum/int8.mjs +118 -118
  140. package/dist/number/enum/uint8.mjs +109 -109
  141. package/dist/number/num-arithmetic-types.mjs +1 -1
  142. package/dist/number/num.mjs +478 -478
  143. package/dist/number/refined-number-utils.mjs +170 -170
  144. package/dist/object/object.mjs +234 -234
  145. package/dist/others/cast-mutable.mjs +33 -33
  146. package/dist/others/cast-readonly.mjs +32 -32
  147. package/dist/others/debounce-function.mjs +13 -13
  148. package/dist/others/fast-deep-equal.mjs +14 -14
  149. package/dist/others/if-then.mjs +29 -29
  150. package/dist/others/tuple.mjs +50 -50
  151. package/dist/others/unknown-to-string.mjs +38 -38
  152. package/dist/promise/promise.mjs +47 -47
  153. package/dist/string/str.mjs +177 -177
  154. package/dist/types.mjs +1 -1
  155. package/package.json +6 -6
  156. package/src/guard/is-type.test.mts +2 -2
  157. package/src/number/branded-types/finite-number.test.mts +1 -1
  158. package/src/number/branded-types/int.test.mts +1 -1
  159. package/src/number/branded-types/int16.test.mts +1 -1
  160. package/src/number/branded-types/int32.test.mts +1 -1
  161. package/src/number/branded-types/non-negative-finite-number.test.mts +1 -1
  162. package/src/number/branded-types/non-negative-int16.test.mts +1 -1
  163. package/src/number/branded-types/non-negative-int32.test.mts +1 -1
  164. package/src/number/branded-types/non-zero-finite-number.test.mts +1 -1
  165. package/src/number/branded-types/non-zero-int.test.mts +1 -1
  166. package/src/number/branded-types/non-zero-int16.test.mts +1 -1
  167. package/src/number/branded-types/non-zero-int32.test.mts +1 -1
  168. package/src/number/branded-types/non-zero-safe-int.test.mts +1 -1
  169. package/src/number/branded-types/non-zero-uint16.test.mts +1 -1
  170. package/src/number/branded-types/non-zero-uint32.test.mts +1 -1
  171. package/src/number/branded-types/positive-finite-number.test.mts +1 -1
  172. package/src/number/branded-types/positive-int.test.mts +1 -1
  173. package/src/number/branded-types/positive-int16.test.mts +1 -1
  174. package/src/number/branded-types/positive-int32.test.mts +1 -1
  175. package/src/number/branded-types/positive-safe-int.test.mts +1 -1
  176. package/src/number/branded-types/positive-uint16.test.mts +1 -1
  177. package/src/number/branded-types/positive-uint32.test.mts +1 -1
  178. package/src/number/branded-types/safe-int.test.mts +1 -1
  179. package/src/number/branded-types/safe-uint.test.mts +1 -1
  180. package/src/number/branded-types/uint.test.mts +1 -1
  181. package/src/number/branded-types/uint16.test.mts +1 -1
  182. package/src/number/branded-types/uint32.test.mts +1 -1
@@ -1,58 +1,58 @@
1
1
  import { Arr } from '../array/index.mjs';
2
2
  import { Optional } from '../functional/index.mjs';
3
3
  import { hasKey, isRecord } from '../guard/index.mjs';
4
- /**
5
- * A collection of type-safe object utility functions providing functional
6
- * programming patterns for object manipulation, including pick, omit, shallow
7
- * equality checks, and more.
8
- *
9
- * All functions maintain TypeScript type safety and support both direct and
10
- * curried usage patterns for better composition with pipe operations.
11
- */
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
12
  export var Obj;
13
13
  (function (Obj) {
14
- /**
15
- * Performs a shallow equality check on two records using a configurable
16
- * equality function. Verifies that both records have the same number of
17
- * entries and that for every key in the first record, the corresponding value
18
- * passes the equality test with the value in the second record.
19
- *
20
- * @example
21
- *
22
- * ```ts
23
- * const obj1 = { name: 'Alice', age: 30 } as const;
24
- *
25
- * const obj2 = { name: 'Alice', age: 30 } as const;
26
- *
27
- * const obj3 = { name: 'Alice', age: 31 } as const;
28
- *
29
- * assert.isTrue(Obj.shallowEq(obj1, obj2));
30
- *
31
- * assert.isFalse(Obj.shallowEq(obj1, obj3));
32
- *
33
- * // Custom equality function
34
- * const obj4 = { value: 1 } as const;
35
- *
36
- * const obj5 = { value: 1.00001 } as const;
37
- *
38
- * const closeEnough = (a: unknown, b: unknown): boolean => {
39
- * if (typeof a === 'number' && typeof b === 'number') {
40
- * return Math.abs(a - b) < 0.001;
41
- * }
42
- *
43
- * return Object.is(a, b);
44
- * };
45
- *
46
- * assert.isTrue(Obj.shallowEq(obj4, obj5, closeEnough));
47
- * ```
48
- *
49
- * @param a - The first record to compare
50
- * @param b - The second record to compare
51
- * @param eq - Optional equality function (defaults to Object.is for strict
52
- * equality)
53
- * @returns `true` if the records are shallowly equal according to the
54
- * equality function, `false` otherwise
55
- */
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+
49
+
50
+
51
+
52
+
53
+
54
+
55
+
56
56
  Obj.shallowEq = (a, b, eq = Object.is) => {
57
57
  const aEntries = Object.entries(a);
58
58
  const bEntries = Object.entries(b);
@@ -66,7 +66,7 @@ export var Obj;
66
66
  const [record, keys] = args;
67
67
  const keysSet = new Set(keys);
68
68
  return (
69
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
69
+
70
70
  Object.fromEntries(Object.entries(record).filter(([k, _v]) => keysSet.has(k))));
71
71
  }
72
72
  case 1: {
@@ -82,15 +82,15 @@ export var Obj;
82
82
  const [record, keys] = args;
83
83
  const keysSet = new Set(keys);
84
84
  return (
85
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
85
+
86
86
  Object.fromEntries(Object.entries(record).filter(([k, _v]) => !keysSet.has(k))));
87
87
  }
88
88
  case 1: {
89
89
  const [keys] = args;
90
90
  return (record) => {
91
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
91
+
92
92
  const result = omit(record,
93
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
93
+
94
94
  keys);
95
95
  return result;
96
96
  };
@@ -98,213 +98,213 @@ export var Obj;
98
98
  }
99
99
  }
100
100
  Obj.omit = omit;
101
- /**
102
- * Creates an object from an array of key-value pairs with precise TypeScript
103
- * typing. This is a type-safe wrapper around `Object.fromEntries` that
104
- * provides better type inference and compile-time guarantees about the
105
- * resulting object structure.
106
- *
107
- * **Type Behavior**:
108
- *
109
- * - When entries is a fixed-length tuple, the exact object type is inferred
110
- * - When entries has dynamic length with union key types, `Partial` is applied
111
- * to prevent incorrect assumptions about which keys will be present
112
- *
113
- * @example
114
- *
115
- * ```ts
116
- * // Fixed-length tuple - exact type inferred
117
- * const entries1 = [
118
- * ['name', 'David'],
119
- * ['age', 25],
120
- * ['active', true],
121
- * ] as const;
122
- *
123
- * const obj1 = Obj.fromEntries(entries1);
124
- *
125
- * assert.deepStrictEqual(obj1, {
126
- * name: 'David',
127
- * age: 25,
128
- * active: true,
129
- * });
130
- *
131
- * // Dynamic length array - Partial type applied
132
- * const dynamicEntries: readonly (readonly ['x' | 'y', number])[] = [
133
- * ['x', 10],
134
- * ['y', 20],
135
- * ] as const;
136
- *
137
- * const obj2 = Obj.fromEntries(dynamicEntries);
138
- *
139
- * assert.deepStrictEqual(obj2, { x: 10, y: 20 });
140
- * ```
141
- *
142
- * @template Entries - The readonly array type of key-value entry tuples
143
- * @param entries - An array of readonly key-value entry tuples `[key, value]`
144
- * @returns An object created from the entries with precise typing
145
- */
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+
109
+
110
+
111
+
112
+
113
+
114
+
115
+
116
+
117
+
118
+
119
+
120
+
121
+
122
+
123
+
124
+
125
+
126
+
127
+
128
+
129
+
130
+
131
+
132
+
133
+
134
+
135
+
136
+
137
+
138
+
139
+
140
+
141
+
142
+
143
+
144
+
145
+
146
146
  Obj.fromEntries = (entries) =>
147
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
147
+
148
148
  Object.fromEntries(entries);
149
- /**
150
- * Transforms every value of a record, leaving the key set untouched.
151
- *
152
- * **Type Behavior**: the result is a mapped type over `keyof R`, so the keys
153
- * — and their optional modifiers — survive verbatim:
154
- * `{ a: number; b?: number }` maps to `{ a: V2; b?: V2 }`, and a record with
155
- * an index signature stays total rather than becoming `Partial`.
156
- *
157
- * This is what `Object.fromEntries(Object.entries(record).map(...))` cannot
158
- * express: an entries array carries no evidence that it still covers every
159
- * key of the record it came from, so its element type is all the return type
160
- * can be built from. Going through a mapped type instead states the
161
- * invariant that a value-only transform preserves the key set.
162
- *
163
- * **Key handling**: keys reach the callback the way `Object.entries` yields
164
- * them, so a numeric key `1` arrives as `'1'`. Symbol-keyed properties are
165
- * not enumerated by `Object.entries`; they are dropped from both the result
166
- * and its type.
167
- *
168
- * @example
169
- *
170
- * <!-- doc:embed:jsdoc:example:./samples/src/object/map-example.mts -->
171
- *
172
- * ```ts
173
- * const scores = { alice: 1, bob: 2 } as const;
174
- *
175
- * const doubled = Obj.map(scores, (value) => value * 2);
176
- *
177
- * assert.deepStrictEqual(doubled, { alice: 2, bob: 4 });
178
- *
179
- * // The key is available as the second argument.
180
- * const labelled = Obj.map(scores, (value, key) => `${key}=${value}`);
181
- *
182
- * assert.deepStrictEqual(labelled, { alice: 'alice=1', bob: 'bob=2' });
183
- * ```
184
- *
185
- * <!-- /doc:embed:jsdoc:example:./samples/src/object/map-example.mts -->
186
- *
187
- * @template R - The type of the source record
188
- * @template V2 - The type the callback returns for every key
189
- * @param record - The record whose values are transformed
190
- * @param mapFn - Called once per own enumerable string key, with the value
191
- * and the key
192
- * @returns A new record with the same keys as `record` and the mapped values
193
- */
149
+
150
+
151
+
152
+
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+
173
+
174
+
175
+
176
+
177
+
178
+
179
+
180
+
181
+
182
+
183
+
184
+
185
+
186
+
187
+
188
+
189
+
190
+
191
+
192
+
193
+
194
194
  Obj.map = (record, mapFn) => {
195
- // `Object.entries` erases both the key and the value type of `R`, so the
196
- // callback is widened once here instead of asserting on every entry.
197
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
195
+
196
+
197
+
198
198
  const mapFnWidened = mapFn;
199
199
  return (
200
- // `Object.entries` enumerates exactly the own enumerable string keys of
201
- // `record`, and nothing here adds or removes an entry, so the result has
202
- // the key set `MappedRecord` claims.
203
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
200
+
201
+
202
+
203
+
204
204
  Object.fromEntries(Object.entries(record).map(([k, v]) => [k, mapFnWidened(v, k)])));
205
205
  };
206
206
  function filter(record, predicate) {
207
- // `Object.entries` erases both the key and the value type of `R`, so the
208
- // callback is widened once here instead of asserting on every entry.
209
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
207
+
208
+
209
+
210
210
  const predicateWidened = predicate;
211
211
  return (
212
- // `Object.entries` enumerates exactly the own enumerable string keys of
213
- // `record`, and filtering only ever removes entries, so the result has a
214
- // subset of those keys — which is what `FilteredRecord` claims.
215
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
212
+
213
+
214
+
215
+
216
216
  Object.fromEntries(Object.entries(record).filter(([k, v]) => predicateWidened(v, k))));
217
217
  }
218
218
  Obj.filter = filter;
219
- /**
220
- * Transforms and drops entries in one pass: the callback returns
221
- * `Optional.some(value)` to keep an entry with a new value, or
222
- * `Optional.none` to drop it.
223
- *
224
- * **Type Behavior**: as with {@link filter}, the surviving keys are the keys
225
- * of the source record made optional, and a record keyed by an index
226
- * signature stays total. Unlike {@link filter}, every kept value takes the
227
- * type the callback returns.
228
- *
229
- * `Optional` rather than `undefined` marks the dropped entries, so a record
230
- * whose values are legitimately `undefined` stays expressible.
231
- *
232
- * **Key handling**: keys reach the callback the way `Object.entries` yields
233
- * them, so a numeric key `1` arrives as `'1'`. Symbol-keyed properties are
234
- * not enumerated by `Object.entries`; they are dropped from both the result
235
- * and its type.
236
- *
237
- * @example
238
- *
239
- * <!-- doc:embed:jsdoc:example:./samples/src/object/filter-map-example.mts -->
240
- *
241
- * ```ts
242
- * const scores = { alice: 1, bob: 2 } as const;
243
- *
244
- * // `Optional.some` keeps an entry with a new value, `Optional.none` drops it.
245
- * const labelled = Obj.filterMap(scores, (value, key) =>
246
- * value > 1 ? Optional.some(`${key}=${value}`) : Optional.none,
247
- * );
248
- *
249
- * assert.deepStrictEqual(labelled, { bob: 'bob=2' });
250
- * ```
251
- *
252
- * <!-- /doc:embed:jsdoc:example:./samples/src/object/filter-map-example.mts -->
253
- *
254
- * @template R - The type of the source record
255
- * @template V2 - The type the callback returns for the entries it keeps
256
- * @param record - The record whose entries are transformed and filtered
257
- * @param mapFn - Called once per own enumerable string key, with the value
258
- * and the key
259
- * @returns A new record holding only the kept entries, with mapped values
260
- */
219
+
220
+
221
+
222
+
223
+
224
+
225
+
226
+
227
+
228
+
229
+
230
+
231
+
232
+
233
+
234
+
235
+
236
+
237
+
238
+
239
+
240
+
241
+
242
+
243
+
244
+
245
+
246
+
247
+
248
+
249
+
250
+
251
+
252
+
253
+
254
+
255
+
256
+
257
+
258
+
259
+
260
+
261
261
  Obj.filterMap = (record, mapFn) => {
262
- // `Object.entries` erases both the key and the value type of `R`, so the
263
- // callback is widened once here instead of asserting on every entry.
264
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
262
+
263
+
264
+
265
265
  const mapFnWidened = mapFn;
266
266
  return (
267
- // `Object.entries` enumerates exactly the own enumerable string keys of
268
- // `record`, and this only ever drops entries or replaces their values, so
269
- // the result has a subset of those keys with `V2` values.
270
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
267
+
268
+
269
+
270
+
271
271
  Object.fromEntries(Object.entries(record).flatMap(([k, v]) => {
272
272
  const mapped = mapFnWidened(v, k);
273
273
  return Optional.isSome(mapped) ? [[k, mapped.value]] : [];
274
274
  })));
275
275
  };
276
- /**
277
- * Merges multiple records into a single record using `Object.assign`.
278
- * Later records override properties from earlier records with the same key.
279
- *
280
- * @example
281
- *
282
- * <!-- doc:embed:jsdoc:example:./samples/src/object/merge-example.mts -->
283
- *
284
- * ```ts
285
- * const a = { a: 0, b: 0 } as const;
286
- *
287
- * const b = { b: 1, c: 0 } as const;
288
- *
289
- * const result = Obj.merge(a, b);
290
- *
291
- * assert.deepStrictEqual(result, { a: 0, b: 1, c: 0 });
292
- * ```
293
- *
294
- * <!-- /doc:embed:jsdoc:example:./samples/src/object/merge-example.mts -->
295
- *
296
- * @param records - The records to merge
297
- * @returns A new record with all properties merged
298
- */
276
+
277
+
278
+
279
+
280
+
281
+
282
+
283
+
284
+
285
+
286
+
287
+
288
+
289
+
290
+
291
+
292
+
293
+
294
+
295
+
296
+
297
+
298
+
299
299
  Obj.merge = (...records) =>
300
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
300
+
301
301
  Object.fromEntries(records.flatMap((r) => Object.entries(r)));
302
302
  function deepPick(...args) {
303
303
  switch (args.length) {
304
304
  case 2: {
305
305
  const [record, path] = args;
306
306
  return (
307
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
307
+
308
308
  deepPickImpl(record, path));
309
309
  }
310
310
  case 1: {
@@ -319,7 +319,7 @@ export var Obj;
319
319
  case 2: {
320
320
  const [record, path] = args;
321
321
  return (
322
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
322
+
323
323
  deepOmitImpl(record, path));
324
324
  }
325
325
  case 1: {
@@ -1,38 +1,38 @@
1
- /**
2
- * Casts a readonly type `T` to its `Mutable<T>` equivalent.
3
- *
4
- * **⚠️ Safety Warning**: This is a type assertion that bypasses TypeScript's
5
- * immutability guarantees. The runtime value remains unchanged - only the type
6
- * system's view of it changes. Use with caution as it can lead to unexpected
7
- * mutations of data that was intended to be immutable.
8
- *
9
- * @template T - The type of the readonly value
10
- * @param readonlyValue - The readonly value to cast to mutable
11
- * @returns The same value with readonly modifiers removed from its type
12
- * @see castDeepMutable - For deeply nested readonly structures
13
- * @see castReadonly - For the opposite operation
14
- */
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
15
  export const castMutable = (readonlyValue) =>
16
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
16
+
17
17
  readonlyValue;
18
- /**
19
- * Casts a readonly type `T` to its `DeepMutable<T>` equivalent, recursively
20
- * removing all readonly modifiers.
21
- *
22
- * **⚠️ Safety Warning**: This recursively bypasses ALL immutability guarantees
23
- * in nested structures. Extremely dangerous for complex data structures as it
24
- * allows mutation at any depth. The runtime value is unchanged - only
25
- * TypeScript's type checking is affected.
26
- *
27
- * @template T - The type of the deeply readonly value
28
- * @param readonlyValue - The deeply readonly value to cast to deeply mutable
29
- * @returns The same value with all readonly modifiers recursively removed from
30
- * its type
31
- * @see castMutable - For shallow mutability casting
32
- * @see castDeepReadonly - For the opposite operation
33
- * @see structuredClone - Recommended for creating safe copies before mutation
34
- */
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
35
  export const castDeepMutable = (readonlyValue) =>
36
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
36
+
37
37
  readonlyValue;
38
38
  //# sourceMappingURL=cast-mutable.mjs.map
@@ -1,37 +1,37 @@
1
- /**
2
- * Casts a mutable type `T` to its `Readonly<T>` equivalent.
3
- *
4
- * This is a safe type assertion that adds immutability constraints at the type
5
- * level. The runtime value remains unchanged - only TypeScript's view of it
6
- * becomes readonly. This helps prevent accidental mutations and makes code
7
- * intentions clearer.
8
- *
9
- * @template T - The type of the mutable value
10
- * @param mutable - The mutable value to cast to readonly
11
- * @returns The same value with readonly modifiers added to its type
12
- * @see castDeepReadonly - For deeply nested structures
13
- * @see castMutable - For the opposite operation (use with caution)
14
- */
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
15
  export const castReadonly = (mutable) =>
16
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
16
+
17
17
  mutable;
18
- /**
19
- * Casts a mutable type `T` to its `DeepReadonly<T>` equivalent, recursively
20
- * adding readonly modifiers.
21
- *
22
- * This is a safe type assertion that adds immutability constraints at ALL
23
- * levels of nesting. Provides complete protection against mutations in complex
24
- * data structures. The runtime value is unchanged - only TypeScript's type
25
- * checking is enhanced.
26
- *
27
- * @template T - The type of the mutable value
28
- * @param mutable - The mutable value to cast to deeply readonly
29
- * @returns The same value with readonly modifiers recursively added to all
30
- * properties
31
- * @see castReadonly - For shallow readonly casting
32
- * @see castDeepMutable - For the opposite operation (use with extreme caution)
33
- */
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
34
  export const castDeepReadonly = (mutable) =>
35
- // eslint-disable-next-line total-functions/no-unsafe-type-assertion
35
+
36
36
  mutable;
37
37
  //# sourceMappingURL=cast-readonly.mjs.map