ts-data-forge 6.13.1 → 7.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 (257) hide show
  1. package/README.md +2 -2
  2. package/dist/array/impl/array-utils-creation.d.mts.map +1 -1
  3. package/dist/array/impl/array-utils-creation.mjs +1 -1
  4. package/dist/array/impl/array-utils-creation.mjs.map +1 -1
  5. package/dist/array/impl/array-utils-iterators.mjs +7 -1
  6. package/dist/array/impl/array-utils-iterators.mjs.map +1 -1
  7. package/dist/array/impl/array-utils-modification.mjs +6 -0
  8. package/dist/array/impl/array-utils-modification.mjs.map +1 -1
  9. package/dist/array/impl/array-utils-reducing-value.d.mts +1 -1
  10. package/dist/array/impl/array-utils-reducing-value.d.mts.map +1 -1
  11. package/dist/array/impl/array-utils-reducing-value.mjs +6 -1
  12. package/dist/array/impl/array-utils-reducing-value.mjs.map +1 -1
  13. package/dist/array/impl/array-utils-search.d.mts +0 -2
  14. package/dist/array/impl/array-utils-search.d.mts.map +1 -1
  15. package/dist/array/impl/array-utils-search.mjs +6 -0
  16. package/dist/array/impl/array-utils-search.mjs.map +1 -1
  17. package/dist/array/impl/array-utils-set-op.d.mts.map +1 -1
  18. package/dist/array/impl/array-utils-set-op.mjs +0 -1
  19. package/dist/array/impl/array-utils-set-op.mjs.map +1 -1
  20. package/dist/array/impl/array-utils-slice-clamped.mjs +6 -0
  21. package/dist/array/impl/array-utils-slice-clamped.mjs.map +1 -1
  22. package/dist/array/impl/array-utils-slicing.mjs +6 -0
  23. package/dist/array/impl/array-utils-slicing.mjs.map +1 -1
  24. package/dist/array/impl/array-utils-transformation.d.mts +1 -1
  25. package/dist/array/impl/array-utils-transformation.d.mts.map +1 -1
  26. package/dist/array/impl/array-utils-transformation.mjs +8 -4
  27. package/dist/array/impl/array-utils-transformation.mjs.map +1 -1
  28. package/dist/array/impl/array-utils-validation.d.mts.map +1 -1
  29. package/dist/array/impl/array-utils-validation.mjs +9 -9
  30. package/dist/array/impl/array-utils-validation.mjs.map +1 -1
  31. package/dist/collections/imap-mapped.d.mts +622 -3
  32. package/dist/collections/imap-mapped.d.mts.map +1 -1
  33. package/dist/collections/imap-mapped.mjs +117 -18
  34. package/dist/collections/imap-mapped.mjs.map +1 -1
  35. package/dist/collections/imap.d.mts +3 -3
  36. package/dist/collections/imap.d.mts.map +1 -1
  37. package/dist/collections/imap.mjs +12 -5
  38. package/dist/collections/imap.mjs.map +1 -1
  39. package/dist/collections/iset-mapped.d.mts +4 -4
  40. package/dist/collections/iset-mapped.d.mts.map +1 -1
  41. package/dist/collections/iset-mapped.mjs +14 -4
  42. package/dist/collections/iset-mapped.mjs.map +1 -1
  43. package/dist/collections/iset.d.mts +2 -2
  44. package/dist/collections/iset.d.mts.map +1 -1
  45. package/dist/collections/iset.mjs +11 -2
  46. package/dist/collections/iset.mjs.map +1 -1
  47. package/dist/collections/queue.mjs +26 -20
  48. package/dist/collections/queue.mjs.map +1 -1
  49. package/dist/collections/stack.mjs +23 -17
  50. package/dist/collections/stack.mjs.map +1 -1
  51. package/dist/entry-point.mjs +6 -0
  52. package/dist/entry-point.mjs.map +1 -1
  53. package/dist/functional/optional/impl/optional-flat-map.d.mts +2 -2
  54. package/dist/functional/pipe.d.mts.map +1 -1
  55. package/dist/functional/pipe.mjs.map +1 -1
  56. package/dist/functional/result/impl/result-flat-map.d.mts +2 -2
  57. package/dist/functional/ternary-result/impl/ternary-result-flat-map.d.mts +5 -3
  58. package/dist/functional/ternary-result/impl/ternary-result-flat-map.d.mts.map +1 -1
  59. package/dist/functional/ternary-result/impl/ternary-result-flat-map.mjs.map +1 -1
  60. package/dist/guard/has-key.d.mts.map +1 -1
  61. package/dist/guard/has-key.mjs +1 -3
  62. package/dist/guard/has-key.mjs.map +1 -1
  63. package/dist/guard/is-non-null-object.d.mts.map +1 -1
  64. package/dist/guard/is-non-null-object.mjs +1 -3
  65. package/dist/guard/is-non-null-object.mjs.map +1 -1
  66. package/dist/guard/key-is-in.d.mts.map +1 -1
  67. package/dist/guard/key-is-in.mjs +1 -3
  68. package/dist/guard/key-is-in.mjs.map +1 -1
  69. package/dist/index.mjs +6 -0
  70. package/dist/index.mjs.map +1 -1
  71. package/dist/iterator/range.mjs +6 -0
  72. package/dist/iterator/range.mjs.map +1 -1
  73. package/dist/json/json.mjs +11 -7
  74. package/dist/json/json.mjs.map +1 -1
  75. package/dist/number/branded-types/finite-number.d.mts +1 -1
  76. package/dist/number/branded-types/index.d.mts +6 -0
  77. package/dist/number/branded-types/index.d.mts.map +1 -1
  78. package/dist/number/branded-types/index.mjs +6 -0
  79. package/dist/number/branded-types/index.mjs.map +1 -1
  80. package/dist/number/branded-types/int.d.mts +1 -2
  81. package/dist/number/branded-types/int.d.mts.map +1 -1
  82. package/dist/number/branded-types/int16.d.mts +2 -3
  83. package/dist/number/branded-types/int16.d.mts.map +1 -1
  84. package/dist/number/branded-types/int32.d.mts +2 -3
  85. package/dist/number/branded-types/int32.d.mts.map +1 -1
  86. package/dist/number/branded-types/negative-finite-number.d.mts +143 -0
  87. package/dist/number/branded-types/negative-finite-number.d.mts.map +1 -0
  88. package/dist/number/branded-types/negative-finite-number.mjs +156 -0
  89. package/dist/number/branded-types/negative-finite-number.mjs.map +1 -0
  90. package/dist/number/branded-types/negative-int.d.mts +120 -0
  91. package/dist/number/branded-types/negative-int.d.mts.map +1 -0
  92. package/dist/number/branded-types/negative-int.mjs +125 -0
  93. package/dist/number/branded-types/negative-int.mjs.map +1 -0
  94. package/dist/number/branded-types/negative-safe-int.d.mts +132 -0
  95. package/dist/number/branded-types/negative-safe-int.d.mts.map +1 -0
  96. package/dist/number/branded-types/negative-safe-int.mjs +136 -0
  97. package/dist/number/branded-types/negative-safe-int.mjs.map +1 -0
  98. package/dist/number/branded-types/non-negative-finite-number.d.mts +1 -1
  99. package/dist/number/branded-types/non-negative-int16.d.mts +1 -1
  100. package/dist/number/branded-types/non-negative-int32.d.mts +1 -1
  101. package/dist/number/branded-types/non-positive-finite-number.d.mts +130 -0
  102. package/dist/number/branded-types/non-positive-finite-number.d.mts.map +1 -0
  103. package/dist/number/branded-types/non-positive-finite-number.mjs +134 -0
  104. package/dist/number/branded-types/non-positive-finite-number.mjs.map +1 -0
  105. package/dist/number/branded-types/non-positive-int.d.mts +224 -0
  106. package/dist/number/branded-types/non-positive-int.d.mts.map +1 -0
  107. package/dist/number/branded-types/non-positive-int.mjs +222 -0
  108. package/dist/number/branded-types/non-positive-int.mjs.map +1 -0
  109. package/dist/number/branded-types/non-positive-safe-int.d.mts +119 -0
  110. package/dist/number/branded-types/non-positive-safe-int.d.mts.map +1 -0
  111. package/dist/number/branded-types/non-positive-safe-int.mjs +116 -0
  112. package/dist/number/branded-types/non-positive-safe-int.mjs.map +1 -0
  113. package/dist/number/branded-types/non-zero-finite-number.d.mts +5 -17
  114. package/dist/number/branded-types/non-zero-finite-number.d.mts.map +1 -1
  115. package/dist/number/branded-types/non-zero-finite-number.mjs +5 -17
  116. package/dist/number/branded-types/non-zero-finite-number.mjs.map +1 -1
  117. package/dist/number/branded-types/non-zero-int.d.mts +5 -33
  118. package/dist/number/branded-types/non-zero-int.d.mts.map +1 -1
  119. package/dist/number/branded-types/non-zero-int.mjs +5 -25
  120. package/dist/number/branded-types/non-zero-int.mjs.map +1 -1
  121. package/dist/number/branded-types/non-zero-int16.d.mts +6 -43
  122. package/dist/number/branded-types/non-zero-int16.d.mts.map +1 -1
  123. package/dist/number/branded-types/non-zero-int16.mjs +5 -25
  124. package/dist/number/branded-types/non-zero-int16.mjs.map +1 -1
  125. package/dist/number/branded-types/non-zero-int32.d.mts +6 -39
  126. package/dist/number/branded-types/non-zero-int32.d.mts.map +1 -1
  127. package/dist/number/branded-types/non-zero-int32.mjs +5 -25
  128. package/dist/number/branded-types/non-zero-int32.mjs.map +1 -1
  129. package/dist/number/branded-types/non-zero-safe-int.d.mts +5 -37
  130. package/dist/number/branded-types/non-zero-safe-int.d.mts.map +1 -1
  131. package/dist/number/branded-types/non-zero-safe-int.mjs +7 -30
  132. package/dist/number/branded-types/non-zero-safe-int.mjs.map +1 -1
  133. package/dist/number/branded-types/non-zero-uint16.d.mts +6 -33
  134. package/dist/number/branded-types/non-zero-uint16.d.mts.map +1 -1
  135. package/dist/number/branded-types/non-zero-uint16.mjs +5 -17
  136. package/dist/number/branded-types/non-zero-uint16.mjs.map +1 -1
  137. package/dist/number/branded-types/non-zero-uint32.d.mts +6 -31
  138. package/dist/number/branded-types/non-zero-uint32.d.mts.map +1 -1
  139. package/dist/number/branded-types/non-zero-uint32.mjs +5 -17
  140. package/dist/number/branded-types/non-zero-uint32.mjs.map +1 -1
  141. package/dist/number/branded-types/positive-finite-number.d.mts +4 -2
  142. package/dist/number/branded-types/positive-finite-number.d.mts.map +1 -1
  143. package/dist/number/branded-types/positive-int.d.mts +4 -2
  144. package/dist/number/branded-types/positive-int.d.mts.map +1 -1
  145. package/dist/number/branded-types/positive-int16.d.mts +4 -2
  146. package/dist/number/branded-types/positive-int16.d.mts.map +1 -1
  147. package/dist/number/branded-types/positive-int32.d.mts +4 -2
  148. package/dist/number/branded-types/positive-int32.d.mts.map +1 -1
  149. package/dist/number/branded-types/positive-safe-int.d.mts +4 -2
  150. package/dist/number/branded-types/positive-safe-int.d.mts.map +1 -1
  151. package/dist/number/branded-types/positive-safe-int.mjs +1 -1
  152. package/dist/number/branded-types/positive-uint16.d.mts +4 -2
  153. package/dist/number/branded-types/positive-uint16.d.mts.map +1 -1
  154. package/dist/number/branded-types/positive-uint32.d.mts +4 -2
  155. package/dist/number/branded-types/positive-uint32.d.mts.map +1 -1
  156. package/dist/number/branded-types/safe-int.d.mts +1 -2
  157. package/dist/number/branded-types/safe-int.d.mts.map +1 -1
  158. package/dist/number/branded-types/safe-int.mjs +2 -2
  159. package/dist/number/branded-types/safe-uint.d.mts +1 -1
  160. package/dist/number/branded-types/safe-uint.mjs +1 -1
  161. package/dist/number/branded-types/uint.d.mts +1 -1
  162. package/dist/number/branded-types/uint16.d.mts +1 -1
  163. package/dist/number/branded-types/uint32.d.mts +1 -1
  164. package/dist/number/index.d.mts +1 -0
  165. package/dist/number/index.d.mts.map +1 -1
  166. package/dist/number/index.mjs +6 -0
  167. package/dist/number/index.mjs.map +1 -1
  168. package/dist/number/num-arithmetic-types.d.mts +74 -0
  169. package/dist/number/num-arithmetic-types.d.mts.map +1 -0
  170. package/dist/number/num-arithmetic-types.mjs +2 -0
  171. package/dist/number/num-arithmetic-types.mjs.map +1 -0
  172. package/dist/number/num.d.mts +53 -9
  173. package/dist/number/num.d.mts.map +1 -1
  174. package/dist/number/num.mjs +67 -15
  175. package/dist/number/num.mjs.map +1 -1
  176. package/dist/number/refined-number-utils.d.mts +12 -9
  177. package/dist/number/refined-number-utils.d.mts.map +1 -1
  178. package/dist/number/refined-number-utils.mjs.map +1 -1
  179. package/dist/object/object.mjs +7 -1
  180. package/dist/object/object.mjs.map +1 -1
  181. package/dist/others/fast-deep-equal.d.mts.map +1 -1
  182. package/dist/others/fast-deep-equal.mjs +0 -1
  183. package/dist/others/fast-deep-equal.mjs.map +1 -1
  184. package/dist/others/unknown-to-string.mjs +2 -2
  185. package/dist/others/unknown-to-string.mjs.map +1 -1
  186. package/package.json +6 -6
  187. package/src/array/impl/array-utils-creation.mts +1 -1
  188. package/src/array/impl/array-utils-iterators.mts +1 -1
  189. package/src/array/impl/array-utils-reducing-value.mts +1 -2
  190. package/src/array/impl/array-utils-search.mts +0 -2
  191. package/src/array/impl/array-utils-set-op.mts +0 -1
  192. package/src/array/impl/array-utils-transformation.mts +8 -6
  193. package/src/array/impl/array-utils-validation.mts +1 -5
  194. package/src/collections/imap-mapped.mts +696 -34
  195. package/src/collections/imap-mapped.test.mts +61 -13
  196. package/src/collections/imap.mts +20 -9
  197. package/src/collections/imap.test.mts +9 -8
  198. package/src/collections/iset-mapped.mts +18 -10
  199. package/src/collections/iset-mapped.test.mts +6 -1
  200. package/src/collections/iset.mts +11 -4
  201. package/src/collections/iset.test.mts +6 -8
  202. package/src/collections/queue.mts +32 -32
  203. package/src/collections/stack.mts +26 -26
  204. package/src/functional/optional/impl/optional-flat-map.mts +2 -2
  205. package/src/functional/optional.test.mts +6 -4
  206. package/src/functional/pipe.mts +0 -1
  207. package/src/functional/pipe.test.mts +2 -1
  208. package/src/functional/result/impl/result-flat-map.mts +2 -2
  209. package/src/functional/result.test.mts +3 -2
  210. package/src/functional/ternary-result/impl/ternary-result-flat-map.mts +5 -3
  211. package/src/functional/ternary-result.test.mts +8 -3
  212. package/src/guard/has-key.mts +1 -3
  213. package/src/guard/is-non-null-object.mts +0 -1
  214. package/src/guard/key-is-in.mts +1 -3
  215. package/src/json/json.mts +5 -8
  216. package/src/json/json.test.mts +2 -2
  217. package/src/number/branded-types/index.mts +6 -0
  218. package/src/number/branded-types/negative-finite-number.mts +210 -0
  219. package/src/number/branded-types/negative-finite-number.test.mts +172 -0
  220. package/src/number/branded-types/negative-int.mts +160 -0
  221. package/src/number/branded-types/negative-int.test.mts +146 -0
  222. package/src/number/branded-types/negative-safe-int.mts +173 -0
  223. package/src/number/branded-types/negative-safe-int.test.mts +120 -0
  224. package/src/number/branded-types/non-positive-finite-number.mts +191 -0
  225. package/src/number/branded-types/non-positive-finite-number.test.mts +286 -0
  226. package/src/number/branded-types/non-positive-int.mts +251 -0
  227. package/src/number/branded-types/non-positive-int.test.mts +197 -0
  228. package/src/number/branded-types/non-positive-safe-int.mts +147 -0
  229. package/src/number/branded-types/non-positive-safe-int.test.mts +223 -0
  230. package/src/number/branded-types/non-zero-finite-number.mts +14 -22
  231. package/src/number/branded-types/non-zero-finite-number.test.mts +0 -12
  232. package/src/number/branded-types/non-zero-int.mts +10 -32
  233. package/src/number/branded-types/non-zero-int.test.mts +0 -20
  234. package/src/number/branded-types/non-zero-int16.mts +8 -32
  235. package/src/number/branded-types/non-zero-int16.test.mts +0 -30
  236. package/src/number/branded-types/non-zero-int32.mts +8 -32
  237. package/src/number/branded-types/non-zero-int32.test.mts +0 -30
  238. package/src/number/branded-types/non-zero-safe-int.mts +10 -37
  239. package/src/number/branded-types/non-zero-safe-int.test.mts +0 -32
  240. package/src/number/branded-types/non-zero-uint16.mts +8 -22
  241. package/src/number/branded-types/non-zero-uint16.test.mts +0 -16
  242. package/src/number/branded-types/non-zero-uint32.mts +8 -22
  243. package/src/number/branded-types/non-zero-uint32.test.mts +0 -16
  244. package/src/number/branded-types/positive-safe-int.mts +1 -1
  245. package/src/number/branded-types/safe-int.mts +2 -2
  246. package/src/number/branded-types/safe-uint.mts +1 -1
  247. package/src/number/index.mts +1 -0
  248. package/src/number/num-arithmetic-types.mts +265 -0
  249. package/src/number/num-arithmetic-types.test.mts +130 -0
  250. package/src/number/num-arithmetic.test.mts +102 -0
  251. package/src/number/num.mts +99 -18
  252. package/src/number/num.test.mts +2 -2
  253. package/src/number/refined-number-utils.mts +19 -9
  254. package/src/object/object.mts +2 -2
  255. package/src/others/fast-deep-equal.mts +0 -2
  256. package/src/others/map-nullable.test.mts +4 -3
  257. package/src/others/unknown-to-string.mts +2 -2
@@ -1,3 +1,5 @@
1
+ /* eslint-disable unicorn/prefer-iterator-to-array-at-end */
2
+ import { type WidenLiteral } from 'ts-type-forge';
1
3
  import { Optional, pipe } from '../functional/index.mjs';
2
4
  import { asUint32 } from '../number/index.mjs';
3
5
  import { tp } from '../others/index.mjs';
@@ -34,25 +36,91 @@ import { type MapSetKeyType, type SizeType } from '../types.mjs';
34
36
  type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
35
37
  // Getting information
36
38
 
37
- /** The number of elements in the map. */
39
+ /**
40
+ * The number of elements in the map.
41
+ *
42
+ * @example
43
+ *
44
+ * ```ts
45
+ * type Point = Readonly<{ x: number; y: number }>;
46
+ *
47
+ * const toKey = (p: Point) => JSON.stringify(p);
48
+ *
49
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
50
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
51
+ *
52
+ * const map = IMapMapped.create<Point, string, string>(
53
+ * [
54
+ * [{ x: 0, y: 0 }, 'origin'],
55
+ * [{ x: 1, y: 0 }, 'right'],
56
+ * ],
57
+ * toKey,
58
+ * fromKey,
59
+ * );
60
+ *
61
+ * assert.isTrue(map.size === 2);
62
+ * ```
63
+ */
38
64
  size: SizeType.Arr;
39
65
 
40
66
  /**
41
67
  * Checks if a key exists in the map.
42
68
  *
69
+ * @example
70
+ *
71
+ * ```ts
72
+ * type Point = Readonly<{ x: number; y: number }>;
73
+ *
74
+ * const toKey = (p: Point) => JSON.stringify(p);
75
+ *
76
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
77
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
78
+ *
79
+ * const map = IMapMapped.create<Point, string, string>(
80
+ * [[{ x: 1, y: 2 }, 'A']],
81
+ * toKey,
82
+ * fromKey,
83
+ * );
84
+ *
85
+ * assert.isTrue(map.has({ x: 1, y: 2 }));
86
+ *
87
+ * assert.isFalse(map.has({ x: 3, y: 4 }));
88
+ * ```
89
+ *
43
90
  * @param key The key to check.
44
91
  * @returns `true` if the key exists, `false` otherwise.
45
92
  */
46
- has: (key: K) => boolean;
93
+ has: (key: K | (WidenLiteral<K> & {})) => boolean;
47
94
 
48
95
  /**
49
96
  * Retrieves the value associated with a key.
50
97
  *
98
+ * @example
99
+ *
100
+ * ```ts
101
+ * type Point = Readonly<{ x: number; y: number }>;
102
+ *
103
+ * const toKey = (p: Point) => JSON.stringify(p);
104
+ *
105
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
106
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
107
+ *
108
+ * const map = IMapMapped.create<Point, string, string>(
109
+ * [[{ x: 1, y: 2 }, 'A']],
110
+ * toKey,
111
+ * fromKey,
112
+ * );
113
+ *
114
+ * assert.deepStrictEqual(map.get({ x: 1, y: 2 }), Optional.some('A'));
115
+ *
116
+ * assert.deepStrictEqual(map.get({ x: 0, y: 0 }), Optional.none);
117
+ * ```
118
+ *
51
119
  * @param key The key to retrieve.
52
120
  * @returns The value associated with the key wrapped with `Optional.some`, or
53
121
  * `Optional.none` if the key does not exist.
54
122
  */
55
- get: (key: K) => Optional<V>;
123
+ get: (key: K | (WidenLiteral<K> & {})) => Optional<V>;
56
124
 
57
125
  // Reducing a value
58
126
 
@@ -61,6 +129,34 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
61
129
  * type predicate overload that narrows the type of values in the map if the
62
130
  * predicate returns true for all elements.
63
131
  *
132
+ * @example
133
+ *
134
+ * ```ts
135
+ * type Point = Readonly<{ x: number; y: number }>;
136
+ *
137
+ * const toKey = (p: Point) => JSON.stringify(p);
138
+ *
139
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
140
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
141
+ *
142
+ * const map = IMapMapped.create<Point, number, string>(
143
+ * [
144
+ * [{ x: 0, y: 0 }, 2],
145
+ * [{ x: 1, y: 0 }, 4],
146
+ * ],
147
+ * toKey,
148
+ * fromKey,
149
+ * );
150
+ *
151
+ * const allEven = map.every((value) => value % 2 === 0);
152
+ *
153
+ * const isNarrowed = map.every((value): value is 2 | 4 => value % 2 === 0);
154
+ *
155
+ * assert.isTrue(allEven);
156
+ *
157
+ * assert.isTrue(isNarrowed);
158
+ * ```
159
+ *
64
160
  * @template W The narrowed type of the values.
65
161
  * @param predicate A function to test each key-value pair.
66
162
  * @returns `true` if all elements satisfy the predicate, `false` otherwise.
@@ -73,6 +169,30 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
73
169
  /**
74
170
  * Checks if at least one element in the map satisfies a predicate.
75
171
  *
172
+ * @example
173
+ *
174
+ * ```ts
175
+ * type Point = Readonly<{ x: number; y: number }>;
176
+ *
177
+ * const toKey = (p: Point) => JSON.stringify(p);
178
+ *
179
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
180
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
181
+ *
182
+ * const map = IMapMapped.create<Point, number, string>(
183
+ * [
184
+ * [{ x: 0, y: 0 }, 3],
185
+ * [{ x: 1, y: 0 }, 7],
186
+ * ],
187
+ * toKey,
188
+ * fromKey,
189
+ * );
190
+ *
191
+ * assert.isTrue(map.some((value) => value > 5));
192
+ *
193
+ * assert.isFalse(map.some((value) => value > 10));
194
+ * ```
195
+ *
76
196
  * @param predicate A function to test each key-value pair.
77
197
  * @returns `true` if at least one element satisfies the predicate, `false`
78
198
  * otherwise.
@@ -84,6 +204,39 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
84
204
  /**
85
205
  * Deletes a key-value pair from the map.
86
206
  *
207
+ * @example
208
+ *
209
+ * ```ts
210
+ * type Point = Readonly<{ x: number; y: number }>;
211
+ *
212
+ * const toKey = (p: Point) => JSON.stringify(p);
213
+ *
214
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
215
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
216
+ *
217
+ * const original = IMapMapped.create<Point, string, string>(
218
+ * [
219
+ * [{ x: 0, y: 0 }, 'origin'],
220
+ * [{ x: 1, y: 0 }, 'right'],
221
+ * ],
222
+ * toKey,
223
+ * fromKey,
224
+ * );
225
+ *
226
+ * const withoutRight = original.delete({ x: 1, y: 0 });
227
+ *
228
+ * assert.deepStrictEqual(
229
+ * original.get({ x: 1, y: 0 }),
230
+ * Optional.some('right'),
231
+ * );
232
+ *
233
+ * assert.deepStrictEqual(withoutRight.get({ x: 1, y: 0 }), Optional.none);
234
+ *
235
+ * assert.isTrue(original.size === 2);
236
+ *
237
+ * assert.isTrue(withoutRight.size === 1);
238
+ * ```
239
+ *
87
240
  * @param key The key to delete.
88
241
  * @returns A new IMapMapped instance without the specified key.
89
242
  */
@@ -92,6 +245,36 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
92
245
  /**
93
246
  * Sets a key-value pair in the map.
94
247
  *
248
+ * @example
249
+ *
250
+ * ```ts
251
+ * type Point = Readonly<{ x: number; y: number }>;
252
+ *
253
+ * const toKey = (p: Point) => JSON.stringify(p);
254
+ *
255
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
256
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
257
+ *
258
+ * const base = IMapMapped.create<Point, string, string>(
259
+ * [[{ x: 0, y: 0 }, 'origin']],
260
+ * toKey,
261
+ * fromKey,
262
+ * );
263
+ *
264
+ * const updated = base.set({ x: 0, y: 0 }, 'home');
265
+ *
266
+ * const extended = base.set({ x: 1, y: 0 }, 'right');
267
+ *
268
+ * assert.deepStrictEqual(base.get({ x: 0, y: 0 }), Optional.some('origin'));
269
+ *
270
+ * assert.deepStrictEqual(updated.get({ x: 0, y: 0 }), Optional.some('home'));
271
+ *
272
+ * assert.deepStrictEqual(
273
+ * extended.get({ x: 1, y: 0 }),
274
+ * Optional.some('right'),
275
+ * );
276
+ * ```
277
+ *
95
278
  * @param key The key to set.
96
279
  * @param value The value to associate with the key.
97
280
  * @returns A new IMapMapped instance with the specified key-value pair.
@@ -101,6 +284,36 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
101
284
  /**
102
285
  * Updates the value associated with a key using an updater function.
103
286
  *
287
+ * @example
288
+ *
289
+ * ```ts
290
+ * type Point = Readonly<{ x: number; y: number }>;
291
+ *
292
+ * const toKey = (p: Point) => JSON.stringify(p);
293
+ *
294
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
295
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
296
+ *
297
+ * const scores = IMapMapped.create<Point, number, string>(
298
+ * [
299
+ * [{ x: 0, y: 0 }, 10],
300
+ * [{ x: 1, y: 0 }, 8],
301
+ * ],
302
+ * toKey,
303
+ * fromKey,
304
+ * );
305
+ *
306
+ * const boosted = scores.update({ x: 0, y: 0 }, (value) => value + 5);
307
+ *
308
+ * const unchanged = scores.update({ x: 9, y: 9 }, (value) => value + 1);
309
+ *
310
+ * assert.deepStrictEqual(boosted.get({ x: 0, y: 0 }), Optional.some(15));
311
+ *
312
+ * assert.deepStrictEqual(scores.get({ x: 0, y: 0 }), Optional.some(10));
313
+ *
314
+ * assert.isTrue(unchanged === scores);
315
+ * ```
316
+ *
104
317
  * @param key The key whose value to update.
105
318
  * @param updater A function that takes the current value and returns the new
106
319
  * value.
@@ -111,6 +324,40 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
111
324
  /**
112
325
  * Applies a series of mutations to the map.
113
326
  *
327
+ * @example
328
+ *
329
+ * ```ts
330
+ * type Point = Readonly<{ x: number; y: number }>;
331
+ *
332
+ * const toKey = (p: Point) => JSON.stringify(p);
333
+ *
334
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
335
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
336
+ *
337
+ * const base = IMapMapped.create<Point, string, string>(
338
+ * [
339
+ * [{ x: 0, y: 0 }, 'origin'],
340
+ * [{ x: 1, y: 0 }, 'right'],
341
+ * ],
342
+ * toKey,
343
+ * fromKey,
344
+ * );
345
+ *
346
+ * const mutated = base.withMutations([
347
+ * { type: 'set', key: { x: 2, y: 0 }, value: 'far' },
348
+ * { type: 'update', key: { x: 1, y: 0 }, updater: (v) => v.toUpperCase() },
349
+ * { type: 'delete', key: { x: 0, y: 0 } },
350
+ * ]);
351
+ *
352
+ * assert.deepStrictEqual(mutated.get({ x: 2, y: 0 }), Optional.some('far'));
353
+ *
354
+ * assert.deepStrictEqual(mutated.get({ x: 1, y: 0 }), Optional.some('RIGHT'));
355
+ *
356
+ * assert.deepStrictEqual(mutated.get({ x: 0, y: 0 }), Optional.none);
357
+ *
358
+ * assert.deepStrictEqual(base.get({ x: 1, y: 0 }), Optional.some('right'));
359
+ * ```
360
+ *
114
361
  * @param actions An array of mutation actions (delete, set, or update).
115
362
  * @returns A new IMapMapped instance with all mutations applied.
116
363
  */
@@ -127,6 +374,33 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
127
374
  /**
128
375
  * Maps the values of the map to new values.
129
376
  *
377
+ * @example
378
+ *
379
+ * ```ts
380
+ * type Point = Readonly<{ x: number; y: number }>;
381
+ *
382
+ * const toKey = (p: Point) => JSON.stringify(p);
383
+ *
384
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
385
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
386
+ *
387
+ * const map = IMapMapped.create<Point, number, string>(
388
+ * [
389
+ * [{ x: 0, y: 0 }, 1],
390
+ * [{ x: 1, y: 0 }, 2],
391
+ * ],
392
+ * toKey,
393
+ * fromKey,
394
+ * );
395
+ *
396
+ * const doubled = map.map((value) => value * 2);
397
+ *
398
+ * assert.deepStrictEqual(Array.from(doubled), [
399
+ * [{ x: 0, y: 0 }, 2],
400
+ * [{ x: 1, y: 0 }, 4],
401
+ * ]);
402
+ * ```
403
+ *
130
404
  * @template V2 The type of the new values.
131
405
  * @param mapFn A function that maps a value and key to a new value.
132
406
  * @returns A new IMapMapped instance with mapped values.
@@ -137,6 +411,33 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
137
411
  * Maps the keys of the map to new keys. Note: The key type cannot be changed
138
412
  * because `toKey` and `fromKey` would become unusable.
139
413
  *
414
+ * @example
415
+ *
416
+ * ```ts
417
+ * type Point = Readonly<{ x: number; y: number }>;
418
+ *
419
+ * const toKey = (p: Point) => JSON.stringify(p);
420
+ *
421
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
422
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
423
+ *
424
+ * const map = IMapMapped.create<Point, string, string>(
425
+ * [
426
+ * [{ x: 0, y: 0 }, 'origin'],
427
+ * [{ x: 1, y: 0 }, 'right'],
428
+ * ],
429
+ * toKey,
430
+ * fromKey,
431
+ * );
432
+ *
433
+ * const shifted = map.mapKeys((p) => ({ x: p.x + 10, y: p.y + 10 }));
434
+ *
435
+ * assert.deepStrictEqual(Array.from(shifted), [
436
+ * [{ x: 10, y: 10 }, 'origin'],
437
+ * [{ x: 11, y: 10 }, 'right'],
438
+ * ]);
439
+ * ```
440
+ *
140
441
  * @param mapFn A function that maps a key to a new key of the same type.
141
442
  * @returns A new IMapMapped instance with mapped keys.
142
443
  */
@@ -145,6 +446,33 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
145
446
  /**
146
447
  * Maps the entries (key-value pairs) of the map to new entries.
147
448
  *
449
+ * @example
450
+ *
451
+ * ```ts
452
+ * type Point = Readonly<{ x: number; y: number }>;
453
+ *
454
+ * const toKey = (p: Point) => JSON.stringify(p);
455
+ *
456
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
457
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
458
+ *
459
+ * const map = IMapMapped.create<Point, number, string>(
460
+ * [
461
+ * [{ x: 0, y: 0 }, 1],
462
+ * [{ x: 1, y: 0 }, 2],
463
+ * ],
464
+ * toKey,
465
+ * fromKey,
466
+ * );
467
+ *
468
+ * const labeled = map.mapEntries(([key, value]) => [key, `value=${value}`]);
469
+ *
470
+ * assert.deepStrictEqual(Array.from(labeled), [
471
+ * [{ x: 0, y: 0 }, 'value=1'],
472
+ * [{ x: 1, y: 0 }, 'value=2'],
473
+ * ]);
474
+ * ```
475
+ *
148
476
  * @template V2 The type of the new values in the entries.
149
477
  * @param mapFn A function that maps an entry to a new entry (key must remain
150
478
  * the same type).
@@ -159,6 +487,37 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
159
487
  /**
160
488
  * Executes a callback function for each key-value pair in the map.
161
489
  *
490
+ * @example
491
+ *
492
+ * ```ts
493
+ * type Point = Readonly<{ x: number; y: number }>;
494
+ *
495
+ * const toKey = (p: Point) => JSON.stringify(p);
496
+ *
497
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
498
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
499
+ *
500
+ * const map = IMapMapped.create<Point, string, string>(
501
+ * [
502
+ * [{ x: 0, y: 0 }, 'origin'],
503
+ * [{ x: 1, y: 0 }, 'right'],
504
+ * ],
505
+ * toKey,
506
+ * fromKey,
507
+ * );
508
+ *
509
+ * const mut_entries: (readonly [Point, string])[] = [];
510
+ *
511
+ * map.forEach((value, key) => {
512
+ * mut_entries.push([key, value]);
513
+ * });
514
+ *
515
+ * assert.deepStrictEqual(mut_entries, [
516
+ * [{ x: 0, y: 0 }, 'origin'],
517
+ * [{ x: 1, y: 0 }, 'right'],
518
+ * ]);
519
+ * ```
520
+ *
162
521
  * @param callbackfn A function to execute for each element.
163
522
  */
164
523
  forEach: (callbackfn: (value: V, key: K) => void) => void;
@@ -168,6 +527,33 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
168
527
  /**
169
528
  * Returns an iterator for the keys in the map.
170
529
  *
530
+ * @example
531
+ *
532
+ * ```ts
533
+ * type Point = Readonly<{ x: number; y: number }>;
534
+ *
535
+ * const toKey = (p: Point) => JSON.stringify(p);
536
+ *
537
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
538
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
539
+ *
540
+ * const map = IMapMapped.create<Point, string, string>(
541
+ * [
542
+ * [{ x: 0, y: 0 }, 'origin'],
543
+ * [{ x: 1, y: 0 }, 'right'],
544
+ * ],
545
+ * toKey,
546
+ * fromKey,
547
+ * );
548
+ *
549
+ * const keys = Array.from(map.keys());
550
+ *
551
+ * assert.deepStrictEqual(keys, [
552
+ * { x: 0, y: 0 },
553
+ * { x: 1, y: 0 },
554
+ * ]);
555
+ * ```
556
+ *
171
557
  * @returns An iterable iterator of keys.
172
558
  */
173
559
  keys: () => IterableIterator<K>;
@@ -175,6 +561,30 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
175
561
  /**
176
562
  * Returns an iterator for the values in the map.
177
563
  *
564
+ * @example
565
+ *
566
+ * ```ts
567
+ * type Point = Readonly<{ x: number; y: number }>;
568
+ *
569
+ * const toKey = (p: Point) => JSON.stringify(p);
570
+ *
571
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
572
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
573
+ *
574
+ * const map = IMapMapped.create<Point, string, string>(
575
+ * [
576
+ * [{ x: 0, y: 0 }, 'origin'],
577
+ * [{ x: 1, y: 0 }, 'right'],
578
+ * ],
579
+ * toKey,
580
+ * fromKey,
581
+ * );
582
+ *
583
+ * const values = Array.from(map.values());
584
+ *
585
+ * assert.deepStrictEqual(values, ['origin', 'right']);
586
+ * ```
587
+ *
178
588
  * @returns An iterable iterator of values.
179
589
  */
180
590
  values: () => IterableIterator<V>;
@@ -182,6 +592,33 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
182
592
  /**
183
593
  * Returns an iterator for the entries (key-value pairs) in the map.
184
594
  *
595
+ * @example
596
+ *
597
+ * ```ts
598
+ * type Point = Readonly<{ x: number; y: number }>;
599
+ *
600
+ * const toKey = (p: Point) => JSON.stringify(p);
601
+ *
602
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
603
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
604
+ *
605
+ * const map = IMapMapped.create<Point, string, string>(
606
+ * [
607
+ * [{ x: 0, y: 0 }, 'origin'],
608
+ * [{ x: 1, y: 0 }, 'right'],
609
+ * ],
610
+ * toKey,
611
+ * fromKey,
612
+ * );
613
+ *
614
+ * const entries = Array.from(map.entries());
615
+ *
616
+ * assert.deepStrictEqual(entries, [
617
+ * [{ x: 0, y: 0 }, 'origin'],
618
+ * [{ x: 1, y: 0 }, 'right'],
619
+ * ]);
620
+ * ```
621
+ *
185
622
  * @returns An iterable iterator of entries.
186
623
  */
187
624
  entries: () => IterableIterator<readonly [K, V]>;
@@ -191,6 +628,31 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
191
628
  /**
192
629
  * Converts the keys of the map to an array.
193
630
  *
631
+ * @example
632
+ *
633
+ * ```ts
634
+ * type Point = Readonly<{ x: number; y: number }>;
635
+ *
636
+ * const toKey = (p: Point) => JSON.stringify(p);
637
+ *
638
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
639
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
640
+ *
641
+ * const map = IMapMapped.create<Point, string, string>(
642
+ * [
643
+ * [{ x: 0, y: 0 }, 'origin'],
644
+ * [{ x: 1, y: 0 }, 'right'],
645
+ * ],
646
+ * toKey,
647
+ * fromKey,
648
+ * );
649
+ *
650
+ * assert.deepStrictEqual(map.toKeysArray(), [
651
+ * { x: 0, y: 0 },
652
+ * { x: 1, y: 0 },
653
+ * ]);
654
+ * ```
655
+ *
194
656
  * @returns A readonly array of keys.
195
657
  */
196
658
  toKeysArray: () => readonly K[];
@@ -198,6 +660,28 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
198
660
  /**
199
661
  * Converts the values of the map to an array.
200
662
  *
663
+ * @example
664
+ *
665
+ * ```ts
666
+ * type Point = Readonly<{ x: number; y: number }>;
667
+ *
668
+ * const toKey = (p: Point) => JSON.stringify(p);
669
+ *
670
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
671
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
672
+ *
673
+ * const map = IMapMapped.create<Point, string, string>(
674
+ * [
675
+ * [{ x: 0, y: 0 }, 'origin'],
676
+ * [{ x: 1, y: 0 }, 'right'],
677
+ * ],
678
+ * toKey,
679
+ * fromKey,
680
+ * );
681
+ *
682
+ * assert.deepStrictEqual(map.toValuesArray(), ['origin', 'right']);
683
+ * ```
684
+ *
201
685
  * @returns A readonly array of values.
202
686
  */
203
687
  toValuesArray: () => readonly V[];
@@ -205,6 +689,31 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
205
689
  /**
206
690
  * Converts the entries (key-value pairs) of the map to an array.
207
691
  *
692
+ * @example
693
+ *
694
+ * ```ts
695
+ * type Point = Readonly<{ x: number; y: number }>;
696
+ *
697
+ * const toKey = (p: Point) => JSON.stringify(p);
698
+ *
699
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
700
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
701
+ *
702
+ * const map = IMapMapped.create<Point, string, string>(
703
+ * [
704
+ * [{ x: 0, y: 0 }, 'origin'],
705
+ * [{ x: 1, y: 0 }, 'right'],
706
+ * ],
707
+ * toKey,
708
+ * fromKey,
709
+ * );
710
+ *
711
+ * assert.deepStrictEqual(map.toEntriesArray(), [
712
+ * [{ x: 0, y: 0 }, 'origin'],
713
+ * [{ x: 1, y: 0 }, 'right'],
714
+ * ]);
715
+ * ```
716
+ *
208
717
  * @returns A readonly array of entries.
209
718
  */
210
719
  toEntriesArray: () => readonly (readonly [K, V])[];
@@ -213,6 +722,31 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
213
722
  * Converts the map to an array of entries (key-value pairs). Alias for
214
723
  * `toEntriesArray`.
215
724
  *
725
+ * @example
726
+ *
727
+ * ```ts
728
+ * type Point = Readonly<{ x: number; y: number }>;
729
+ *
730
+ * const toKey = (p: Point) => JSON.stringify(p);
731
+ *
732
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
733
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
734
+ *
735
+ * const map = IMapMapped.create<Point, string, string>(
736
+ * [
737
+ * [{ x: 0, y: 0 }, 'origin'],
738
+ * [{ x: 1, y: 0 }, 'right'],
739
+ * ],
740
+ * toKey,
741
+ * fromKey,
742
+ * );
743
+ *
744
+ * assert.deepStrictEqual(map.toArray(), [
745
+ * [{ x: 0, y: 0 }, 'origin'],
746
+ * [{ x: 1, y: 0 }, 'right'],
747
+ * ]);
748
+ * ```
749
+ *
216
750
  * @returns A readonly array of entries.
217
751
  */
218
752
  toArray: () => readonly (readonly [K, V])[];
@@ -220,6 +754,29 @@ type IMapMappedInterface<K, V, KM extends MapSetKeyType> = Readonly<{
220
754
  /**
221
755
  * Returns the underlying readonly JavaScript Map.
222
756
  *
757
+ * @example
758
+ *
759
+ * ```ts
760
+ * type Point = Readonly<{ x: number; y: number }>;
761
+ *
762
+ * const toKey = (p: Point) => JSON.stringify(p);
763
+ *
764
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
765
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
766
+ *
767
+ * const map = IMapMapped.create<Point, string, string>(
768
+ * [[{ x: 1, y: 2 }, 'A']],
769
+ * toKey,
770
+ * fromKey,
771
+ * );
772
+ *
773
+ * const raw = map.toRawMap();
774
+ *
775
+ * assert.isTrue(isMap(raw));
776
+ *
777
+ * assert.isTrue(raw.get(toKey({ x: 1, y: 2 })) === 'A');
778
+ * ```
779
+ *
223
780
  * @returns The raw ReadonlyMap instance.
224
781
  */
225
782
  toRawMap: () => ReadonlyMap<KM, V>;
@@ -276,6 +833,30 @@ export namespace IMapMapped {
276
833
  * @template K The type of the custom keys.
277
834
  * @template V The type of the values.
278
835
  * @template KM The type of the mapped primitive keys.
836
+ * @example
837
+ *
838
+ * ```ts
839
+ * type Point = Readonly<{ x: number; y: number }>;
840
+ *
841
+ * const toKey = (p: Point) => JSON.stringify(p);
842
+ *
843
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
844
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
845
+ *
846
+ * const map = IMapMapped.create<Point, string, string>(
847
+ * [
848
+ * [{ x: 0, y: 0 }, 'origin'],
849
+ * [{ x: 1, y: 0 }, 'right'],
850
+ * ],
851
+ * toKey,
852
+ * fromKey,
853
+ * );
854
+ *
855
+ * assert.isTrue(map.size === 2);
856
+ *
857
+ * assert.deepStrictEqual(map.get({ x: 0, y: 0 }), Optional.some('origin'));
858
+ * ```
859
+ *
279
860
  * @param iterable An iterable of key-value pairs using the custom key type.
280
861
  * @param toKey A function that converts a custom key `K` to a primitive key
281
862
  * `KM`. This function must be deterministic and produce unique values for
@@ -306,6 +887,45 @@ export namespace IMapMapped {
306
887
  * @template K The type of the custom keys.
307
888
  * @template V The type of the values.
308
889
  * @template KM The type of the mapped primitive keys.
890
+ * @example
891
+ *
892
+ * ```ts
893
+ * type Point = Readonly<{ x: number; y: number }>;
894
+ *
895
+ * const toKey = (p: Point) => JSON.stringify(p);
896
+ *
897
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
898
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
899
+ *
900
+ * const first = IMapMapped.create<Point, string, string>(
901
+ * [
902
+ * [{ x: 0, y: 0 }, 'origin'],
903
+ * [{ x: 1, y: 0 }, 'right'],
904
+ * ],
905
+ * toKey,
906
+ * fromKey,
907
+ * );
908
+ *
909
+ * const second = IMapMapped.create<Point, string, string>(
910
+ * [
911
+ * [{ x: 1, y: 0 }, 'right'],
912
+ * [{ x: 0, y: 0 }, 'origin'],
913
+ * ],
914
+ * toKey,
915
+ * fromKey,
916
+ * );
917
+ *
918
+ * const third = IMapMapped.create<Point, string, string>(
919
+ * [[{ x: 0, y: 0 }, 'different']],
920
+ * toKey,
921
+ * fromKey,
922
+ * );
923
+ *
924
+ * assert.isTrue(IMapMapped.equal(first, second));
925
+ *
926
+ * assert.isFalse(IMapMapped.equal(first, third));
927
+ * ```
928
+ *
309
929
  * @param a The first IMapMapped instance to compare.
310
930
  * @param b The second IMapMapped instance to compare.
311
931
  * @returns `true` if the maps contain exactly the same key-value pairs,
@@ -314,7 +934,12 @@ export namespace IMapMapped {
314
934
  export const equal = <K, V, KM extends MapSetKeyType>(
315
935
  a: IMapMapped<K, V, KM>,
316
936
  b: IMapMapped<K, V, KM>,
317
- ): boolean => a.size === b.size && a.every((v, k) => b.get(k) === v);
937
+ ): boolean =>
938
+ a.size === b.size &&
939
+ a.every(
940
+ (v, k) =>
941
+ pipe(b.get(k)).map((bv) => Optional.isSome(bv) && bv.value === v).value,
942
+ );
318
943
  }
319
944
 
320
945
  /**
@@ -382,16 +1007,17 @@ class IMapMappedClass<K, V, KM extends MapSetKeyType>
382
1007
  }
383
1008
 
384
1009
  /** @inheritdoc */
385
- has(key: K): boolean {
386
- return this.#map.has(this.#toKey(key));
1010
+ has(key: K | (WidenLiteral<K> & {})): boolean {
1011
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
1012
+ return this.#map.has(this.#toKey(key as K));
387
1013
  }
388
1014
 
389
1015
  /** @inheritdoc */
390
- get(key: K): Optional<V> {
1016
+ get(key: K | (WidenLiteral<K> & {})): Optional<V> {
391
1017
  if (!this.has(key)) return Optional.none;
392
1018
 
393
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
394
- return Optional.some(this.#map.get(this.#toKey(key))!);
1019
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion, total-functions/no-unsafe-type-assertion
1020
+ return Optional.some(this.#map.get(this.#toKey(key as K))!);
395
1021
  }
396
1022
 
397
1023
  /** @inheritdoc */
@@ -445,7 +1071,9 @@ class IMapMappedClass<K, V, KM extends MapSetKeyType>
445
1071
 
446
1072
  /** @inheritdoc */
447
1073
  set(key: K, value: V): IMapMapped<K, V, KM> {
448
- if (value === this.get(key)) return this; // has no changes
1074
+ const curr = this.get(key);
1075
+
1076
+ if (Optional.isSome(curr) && value === curr.value) return this;
449
1077
 
450
1078
  const keyMapped = this.#toKey(key);
451
1079
 
@@ -457,15 +1085,15 @@ class IMapMappedClass<K, V, KM extends MapSetKeyType>
457
1085
  this.#toKey,
458
1086
  this.#fromKey,
459
1087
  );
460
- } else {
461
- return IMapMapped.create(
462
- Array.from(this.#map, ([km, v]) =>
463
- tp(this.#fromKey(km), Object.is(km, keyMapped) ? value : v),
464
- ),
465
- this.#toKey,
466
- this.#fromKey,
467
- );
468
1088
  }
1089
+
1090
+ return IMapMapped.create(
1091
+ Array.from(this.#map, ([km, v]) =>
1092
+ tp(this.#fromKey(km), Object.is(km, keyMapped) ? value : v),
1093
+ ),
1094
+ this.#toKey,
1095
+ this.#fromKey,
1096
+ );
469
1097
  }
470
1098
 
471
1099
  /** @inheritdoc */
@@ -485,14 +1113,11 @@ class IMapMappedClass<K, V, KM extends MapSetKeyType>
485
1113
  const keyMapped = this.#toKey(key);
486
1114
 
487
1115
  return IMapMapped.create(
488
- Array.from(
489
- this.#map.entries(),
490
- (keyValue) =>
491
- pipe(keyValue)
492
- .map(([km, v]) =>
493
- tp(km, Object.is(km, keyMapped) ? updater(curr.value) : v),
494
- )
495
- .map(([km, v]) => tp(this.#fromKey(km), v)).value,
1116
+ Array.from(this.#map, ([km, v]) =>
1117
+ tp(
1118
+ this.#fromKey(km),
1119
+ Object.is(km, keyMapped) ? updater(curr.value) : v,
1120
+ ),
496
1121
  ),
497
1122
  this.#toKey,
498
1123
  this.#fromKey,
@@ -509,7 +1134,13 @@ class IMapMappedClass<K, V, KM extends MapSetKeyType>
509
1134
  ): IMapMapped<K, V, KM> {
510
1135
  const mut_result = new Map<KM, V>(this.#map);
511
1136
 
512
- for (const action of actions) {
1137
+ const updateFn = (
1138
+ action: Readonly<
1139
+ | { type: 'delete'; key: K }
1140
+ | { type: 'set'; key: K; value: V }
1141
+ | { type: 'update'; key: K; updater: (value: V) => V }
1142
+ >,
1143
+ ): void => {
513
1144
  const key = this.#toKey(action.key);
514
1145
 
515
1146
  switch (action.type) {
@@ -541,6 +1172,10 @@ class IMapMappedClass<K, V, KM extends MapSetKeyType>
541
1172
  break;
542
1173
  }
543
1174
  }
1175
+ };
1176
+
1177
+ for (const action of actions) {
1178
+ updateFn(action);
544
1179
  }
545
1180
 
546
1181
  return IMapMapped.create<K, V, KM>(
@@ -581,12 +1216,41 @@ class IMapMappedClass<K, V, KM extends MapSetKeyType>
581
1216
 
582
1217
  /** @inheritdoc */
583
1218
  forEach(callbackfn: (value: V, key: K) => void): void {
584
- for (const [km, value] of this.#map.entries()) {
1219
+ for (const [km, value] of this.#map) {
585
1220
  callbackfn(value, this.#fromKey(km));
586
1221
  }
587
1222
  }
588
1223
 
589
- /** @inheritdoc */
1224
+ /**
1225
+ * @example
1226
+ *
1227
+ * ```ts
1228
+ * type Point = Readonly<{ x: number; y: number }>;
1229
+ *
1230
+ * const toKey = (p: Point) => JSON.stringify(p);
1231
+ *
1232
+ * // eslint-disable-next-line total-functions/no-unsafe-type-assertion
1233
+ * const fromKey = (key: string) => JSON.parse(key) as Point;
1234
+ *
1235
+ * const map = IMapMapped.create<Point, string, string>(
1236
+ * [
1237
+ * [{ x: 0, y: 0 }, 'origin'],
1238
+ * [{ x: 1, y: 0 }, 'right'],
1239
+ * ],
1240
+ * toKey,
1241
+ * fromKey,
1242
+ * );
1243
+ *
1244
+ * const collected = Array.from(map);
1245
+ *
1246
+ * assert.deepStrictEqual(collected, [
1247
+ * [{ x: 0, y: 0 }, 'origin'],
1248
+ * [{ x: 1, y: 0 }, 'right'],
1249
+ * ]);
1250
+ * ```
1251
+ *
1252
+ * @inheritdoc
1253
+ */
590
1254
  *[Symbol.iterator](): Iterator<readonly [K, V]> {
591
1255
  for (const e of this.entries()) {
592
1256
  yield e;
@@ -601,15 +1265,13 @@ class IMapMappedClass<K, V, KM extends MapSetKeyType>
601
1265
  }
602
1266
 
603
1267
  /** @inheritdoc */
604
- *values(): IterableIterator<V> {
605
- for (const v of this.#map.values()) {
606
- yield v;
607
- }
1268
+ values(): IterableIterator<V> {
1269
+ return this.#map.values();
608
1270
  }
609
1271
 
610
1272
  /** @inheritdoc */
611
1273
  *entries(): IterableIterator<readonly [K, V]> {
612
- for (const [km, v] of this.#map.entries()) {
1274
+ for (const [km, v] of this.#map) {
613
1275
  yield [this.#fromKey(km), v];
614
1276
  }
615
1277
  }