ts-data-forge 3.2.0 → 3.3.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.
- package/README.md +45 -21
- package/dist/array/impl/array-utils-creation.d.mts +116 -0
- package/dist/array/impl/array-utils-creation.d.mts.map +1 -0
- package/dist/array/impl/array-utils-creation.mjs +110 -0
- package/dist/array/impl/array-utils-creation.mjs.map +1 -0
- package/dist/array/impl/array-utils-element-access.d.mts +61 -0
- package/dist/array/impl/array-utils-element-access.d.mts.map +1 -0
- package/dist/array/impl/array-utils-element-access.mjs +66 -0
- package/dist/array/impl/array-utils-element-access.mjs.map +1 -0
- package/dist/array/impl/array-utils-iterators.d.mts +59 -0
- package/dist/array/impl/array-utils-iterators.d.mts.map +1 -0
- package/dist/array/impl/array-utils-iterators.mjs +104 -0
- package/dist/array/impl/array-utils-iterators.mjs.map +1 -0
- package/dist/array/impl/array-utils-modification.d.mts +154 -0
- package/dist/array/impl/array-utils-modification.d.mts.map +1 -0
- package/dist/array/impl/array-utils-modification.mjs +139 -0
- package/dist/array/impl/array-utils-modification.mjs.map +1 -0
- package/dist/array/impl/array-utils-reducing-value.d.mts +214 -0
- package/dist/array/impl/array-utils-reducing-value.d.mts.map +1 -0
- package/dist/array/impl/array-utils-reducing-value.mjs +160 -0
- package/dist/array/impl/array-utils-reducing-value.mjs.map +1 -0
- package/dist/array/impl/array-utils-search.d.mts +179 -0
- package/dist/array/impl/array-utils-search.d.mts.map +1 -0
- package/dist/array/impl/array-utils-search.mjs +153 -0
- package/dist/array/impl/array-utils-search.mjs.map +1 -0
- package/dist/array/impl/array-utils-set-op.d.mts +100 -0
- package/dist/array/impl/array-utils-set-op.d.mts.map +1 -0
- package/dist/array/impl/array-utils-set-op.mjs +137 -0
- package/dist/array/impl/array-utils-set-op.mjs.map +1 -0
- package/dist/array/impl/array-utils-size.d.mts +24 -0
- package/dist/array/impl/array-utils-size.d.mts.map +1 -0
- package/dist/array/impl/array-utils-size.mjs +28 -0
- package/dist/array/impl/array-utils-size.mjs.map +1 -0
- package/dist/array/impl/array-utils-slice-clamped.d.mts +18 -0
- package/dist/array/impl/array-utils-slice-clamped.d.mts.map +1 -0
- package/dist/array/impl/array-utils-slice-clamped.mjs +49 -0
- package/dist/array/impl/array-utils-slice-clamped.mjs.map +1 -0
- package/dist/array/impl/array-utils-slicing.d.mts +120 -0
- package/dist/array/impl/array-utils-slicing.d.mts.map +1 -0
- package/dist/array/impl/array-utils-slicing.mjs +140 -0
- package/dist/array/impl/array-utils-slicing.mjs.map +1 -0
- package/dist/array/impl/array-utils-transformation.d.mts +348 -0
- package/dist/array/impl/array-utils-transformation.d.mts.map +1 -0
- package/dist/array/impl/array-utils-transformation.mjs +331 -0
- package/dist/array/impl/array-utils-transformation.mjs.map +1 -0
- package/dist/array/impl/array-utils-validation.d.mts +149 -0
- package/dist/array/impl/array-utils-validation.d.mts.map +1 -0
- package/dist/array/impl/array-utils-validation.mjs +166 -0
- package/dist/array/impl/array-utils-validation.mjs.map +1 -0
- package/dist/array/impl/index.d.mts +13 -0
- package/dist/array/impl/index.d.mts.map +1 -0
- package/dist/array/impl/index.mjs +13 -0
- package/dist/array/impl/index.mjs.map +1 -0
- package/dist/array/index.d.mts +1 -1
- package/dist/array/index.d.mts.map +1 -1
- package/dist/array/index.mjs +2 -1
- package/dist/array/index.mjs.map +1 -1
- package/dist/collections/imap-mapped.d.mts +83 -253
- package/dist/collections/imap-mapped.d.mts.map +1 -1
- package/dist/collections/imap-mapped.mjs +33 -164
- package/dist/collections/imap-mapped.mjs.map +1 -1
- package/dist/collections/imap.d.mts +436 -163
- package/dist/collections/imap.d.mts.map +1 -1
- package/dist/collections/imap.mjs +74 -94
- package/dist/collections/imap.mjs.map +1 -1
- package/dist/collections/iset-mapped.d.mts +828 -345
- package/dist/collections/iset-mapped.d.mts.map +1 -1
- package/dist/collections/iset-mapped.mjs +200 -242
- package/dist/collections/iset-mapped.mjs.map +1 -1
- package/dist/collections/iset.d.mts +397 -205
- package/dist/collections/iset.d.mts.map +1 -1
- package/dist/collections/iset.mjs +102 -184
- package/dist/collections/iset.mjs.map +1 -1
- package/dist/collections/queue.d.mts +155 -135
- package/dist/collections/queue.d.mts.map +1 -1
- package/dist/collections/queue.mjs +55 -156
- package/dist/collections/queue.mjs.map +1 -1
- package/dist/collections/stack.d.mts +154 -154
- package/dist/collections/stack.d.mts.map +1 -1
- package/dist/collections/stack.mjs +54 -203
- package/dist/collections/stack.mjs.map +1 -1
- package/dist/entry-point.d.mts +3 -0
- package/dist/entry-point.d.mts.map +1 -0
- package/dist/entry-point.mjs +62 -0
- package/dist/entry-point.mjs.map +1 -0
- package/dist/expect-type.d.mts +43 -172
- package/dist/expect-type.d.mts.map +1 -1
- package/dist/expect-type.mjs +43 -172
- package/dist/expect-type.mjs.map +1 -1
- package/dist/functional/match.d.mts +35 -140
- package/dist/functional/match.d.mts.map +1 -1
- package/dist/functional/match.mjs.map +1 -1
- package/dist/functional/optional.d.mts +282 -160
- package/dist/functional/optional.d.mts.map +1 -1
- package/dist/functional/optional.mjs +131 -71
- package/dist/functional/optional.mjs.map +1 -1
- package/dist/functional/pipe.d.mts +59 -113
- package/dist/functional/pipe.d.mts.map +1 -1
- package/dist/functional/pipe.mjs.map +1 -1
- package/dist/functional/result.d.mts +433 -332
- package/dist/functional/result.d.mts.map +1 -1
- package/dist/functional/result.mjs +233 -239
- package/dist/functional/result.mjs.map +1 -1
- package/dist/globals.d.mts +12 -5
- package/dist/guard/has-key.d.mts +23 -74
- package/dist/guard/has-key.d.mts.map +1 -1
- package/dist/guard/has-key.mjs +23 -74
- package/dist/guard/has-key.mjs.map +1 -1
- package/dist/guard/is-non-empty-string.d.mts +20 -87
- package/dist/guard/is-non-empty-string.d.mts.map +1 -1
- package/dist/guard/is-non-empty-string.mjs +20 -87
- package/dist/guard/is-non-empty-string.mjs.map +1 -1
- package/dist/guard/is-non-null-object.d.mts +14 -84
- package/dist/guard/is-non-null-object.d.mts.map +1 -1
- package/dist/guard/is-non-null-object.mjs +14 -84
- package/dist/guard/is-non-null-object.mjs.map +1 -1
- package/dist/guard/is-primitive.d.mts +13 -126
- package/dist/guard/is-primitive.d.mts.map +1 -1
- package/dist/guard/is-primitive.mjs +13 -126
- package/dist/guard/is-primitive.mjs.map +1 -1
- package/dist/guard/is-record.d.mts +21 -132
- package/dist/guard/is-record.d.mts.map +1 -1
- package/dist/guard/is-record.mjs +21 -132
- package/dist/guard/is-record.mjs.map +1 -1
- package/dist/guard/is-type.d.mts +201 -238
- package/dist/guard/is-type.d.mts.map +1 -1
- package/dist/guard/is-type.mjs +201 -238
- package/dist/guard/is-type.mjs.map +1 -1
- package/dist/guard/key-is-in.d.mts +22 -139
- package/dist/guard/key-is-in.d.mts.map +1 -1
- package/dist/guard/key-is-in.mjs +22 -139
- package/dist/guard/key-is-in.mjs.map +1 -1
- package/dist/index.d.mts +0 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +0 -1
- package/dist/index.mjs.map +1 -1
- package/dist/iterator/range.d.mts +29 -62
- package/dist/iterator/range.d.mts.map +1 -1
- package/dist/iterator/range.mjs.map +1 -1
- package/dist/json/json.d.mts +191 -121
- package/dist/json/json.d.mts.map +1 -1
- package/dist/json/json.mjs +238 -136
- package/dist/json/json.mjs.map +1 -1
- package/dist/number/branded-types/finite-number.d.mts +24 -156
- package/dist/number/branded-types/finite-number.d.mts.map +1 -1
- package/dist/number/branded-types/finite-number.mjs +27 -159
- package/dist/number/branded-types/finite-number.mjs.map +1 -1
- package/dist/number/branded-types/int.d.mts +122 -120
- package/dist/number/branded-types/int.d.mts.map +1 -1
- package/dist/number/branded-types/int.mjs +122 -120
- package/dist/number/branded-types/int.mjs.map +1 -1
- package/dist/number/branded-types/int16.d.mts +22 -30
- package/dist/number/branded-types/int16.d.mts.map +1 -1
- package/dist/number/branded-types/int16.mjs +22 -30
- package/dist/number/branded-types/int16.mjs.map +1 -1
- package/dist/number/branded-types/int32.d.mts +22 -31
- package/dist/number/branded-types/int32.d.mts.map +1 -1
- package/dist/number/branded-types/int32.mjs +22 -31
- package/dist/number/branded-types/int32.mjs.map +1 -1
- package/dist/number/branded-types/non-negative-finite-number.d.mts +28 -36
- package/dist/number/branded-types/non-negative-finite-number.d.mts.map +1 -1
- package/dist/number/branded-types/non-negative-finite-number.mjs +31 -39
- package/dist/number/branded-types/non-negative-finite-number.mjs.map +1 -1
- package/dist/number/branded-types/non-negative-int16.d.mts +24 -34
- package/dist/number/branded-types/non-negative-int16.d.mts.map +1 -1
- package/dist/number/branded-types/non-negative-int16.mjs +24 -34
- package/dist/number/branded-types/non-negative-int16.mjs.map +1 -1
- package/dist/number/branded-types/non-negative-int32.d.mts +26 -35
- package/dist/number/branded-types/non-negative-int32.d.mts.map +1 -1
- package/dist/number/branded-types/non-negative-int32.mjs +26 -35
- package/dist/number/branded-types/non-negative-int32.mjs.map +1 -1
- package/dist/number/branded-types/non-zero-finite-number.d.mts +22 -37
- package/dist/number/branded-types/non-zero-finite-number.d.mts.map +1 -1
- package/dist/number/branded-types/non-zero-finite-number.mjs +25 -40
- package/dist/number/branded-types/non-zero-finite-number.mjs.map +1 -1
- package/dist/number/branded-types/non-zero-int.d.mts +15 -30
- package/dist/number/branded-types/non-zero-int.d.mts.map +1 -1
- package/dist/number/branded-types/non-zero-int.mjs +15 -30
- package/dist/number/branded-types/non-zero-int.mjs.map +1 -1
- package/dist/number/branded-types/non-zero-int16.d.mts +27 -35
- package/dist/number/branded-types/non-zero-int16.d.mts.map +1 -1
- package/dist/number/branded-types/non-zero-int16.mjs +27 -35
- package/dist/number/branded-types/non-zero-int16.mjs.map +1 -1
- package/dist/number/branded-types/non-zero-int32.d.mts +29 -36
- package/dist/number/branded-types/non-zero-int32.d.mts.map +1 -1
- package/dist/number/branded-types/non-zero-int32.mjs +29 -36
- package/dist/number/branded-types/non-zero-int32.mjs.map +1 -1
- package/dist/number/branded-types/non-zero-safe-int.d.mts +37 -38
- package/dist/number/branded-types/non-zero-safe-int.d.mts.map +1 -1
- package/dist/number/branded-types/non-zero-safe-int.mjs +39 -40
- package/dist/number/branded-types/non-zero-safe-int.mjs.map +1 -1
- package/dist/number/branded-types/non-zero-uint16.d.mts +24 -35
- package/dist/number/branded-types/non-zero-uint16.d.mts.map +1 -1
- package/dist/number/branded-types/non-zero-uint16.mjs +24 -35
- package/dist/number/branded-types/non-zero-uint16.mjs.map +1 -1
- package/dist/number/branded-types/non-zero-uint32.d.mts +24 -35
- package/dist/number/branded-types/non-zero-uint32.d.mts.map +1 -1
- package/dist/number/branded-types/non-zero-uint32.mjs +24 -35
- package/dist/number/branded-types/non-zero-uint32.mjs.map +1 -1
- package/dist/number/branded-types/positive-finite-number.d.mts +26 -40
- package/dist/number/branded-types/positive-finite-number.d.mts.map +1 -1
- package/dist/number/branded-types/positive-finite-number.mjs +29 -43
- package/dist/number/branded-types/positive-finite-number.mjs.map +1 -1
- package/dist/number/branded-types/positive-int.d.mts +133 -123
- package/dist/number/branded-types/positive-int.d.mts.map +1 -1
- package/dist/number/branded-types/positive-int.mjs +133 -123
- package/dist/number/branded-types/positive-int.mjs.map +1 -1
- package/dist/number/branded-types/positive-int16.d.mts +24 -35
- package/dist/number/branded-types/positive-int16.d.mts.map +1 -1
- package/dist/number/branded-types/positive-int16.mjs +24 -35
- package/dist/number/branded-types/positive-int16.mjs.map +1 -1
- package/dist/number/branded-types/positive-int32.d.mts +24 -35
- package/dist/number/branded-types/positive-int32.d.mts.map +1 -1
- package/dist/number/branded-types/positive-int32.mjs +24 -35
- package/dist/number/branded-types/positive-int32.mjs.map +1 -1
- package/dist/number/branded-types/positive-safe-int.d.mts +159 -33
- package/dist/number/branded-types/positive-safe-int.d.mts.map +1 -1
- package/dist/number/branded-types/positive-safe-int.mjs +160 -34
- package/dist/number/branded-types/positive-safe-int.mjs.map +1 -1
- package/dist/number/branded-types/positive-uint16.d.mts +24 -35
- package/dist/number/branded-types/positive-uint16.d.mts.map +1 -1
- package/dist/number/branded-types/positive-uint16.mjs +24 -35
- package/dist/number/branded-types/positive-uint16.mjs.map +1 -1
- package/dist/number/branded-types/positive-uint32.d.mts +26 -36
- package/dist/number/branded-types/positive-uint32.d.mts.map +1 -1
- package/dist/number/branded-types/positive-uint32.mjs +26 -36
- package/dist/number/branded-types/positive-uint32.mjs.map +1 -1
- package/dist/number/branded-types/safe-int.d.mts +140 -99
- package/dist/number/branded-types/safe-int.d.mts.map +1 -1
- package/dist/number/branded-types/safe-int.mjs +142 -101
- package/dist/number/branded-types/safe-int.mjs.map +1 -1
- package/dist/number/branded-types/safe-uint.d.mts +24 -33
- package/dist/number/branded-types/safe-uint.d.mts.map +1 -1
- package/dist/number/branded-types/safe-uint.mjs +25 -34
- package/dist/number/branded-types/safe-uint.mjs.map +1 -1
- package/dist/number/branded-types/uint.d.mts +121 -30
- package/dist/number/branded-types/uint.d.mts.map +1 -1
- package/dist/number/branded-types/uint.mjs +121 -30
- package/dist/number/branded-types/uint.mjs.map +1 -1
- package/dist/number/branded-types/uint16.d.mts +26 -34
- package/dist/number/branded-types/uint16.d.mts.map +1 -1
- package/dist/number/branded-types/uint16.mjs +26 -34
- package/dist/number/branded-types/uint16.mjs.map +1 -1
- package/dist/number/branded-types/uint32.d.mts +26 -68
- package/dist/number/branded-types/uint32.d.mts.map +1 -1
- package/dist/number/branded-types/uint32.mjs +26 -68
- package/dist/number/branded-types/uint32.mjs.map +1 -1
- package/dist/number/enum/int8.d.mts +37 -101
- package/dist/number/enum/int8.d.mts.map +1 -1
- package/dist/number/enum/int8.mjs +39 -170
- package/dist/number/enum/int8.mjs.map +1 -1
- package/dist/number/enum/uint8.d.mts +45 -55
- package/dist/number/enum/uint8.d.mts.map +1 -1
- package/dist/number/enum/uint8.mjs +46 -155
- package/dist/number/enum/uint8.mjs.map +1 -1
- package/dist/number/num.d.mts +145 -206
- package/dist/number/num.d.mts.map +1 -1
- package/dist/number/num.mjs +143 -199
- package/dist/number/num.mjs.map +1 -1
- package/dist/number/refined-number-utils.d.mts +97 -21
- package/dist/number/refined-number-utils.d.mts.map +1 -1
- package/dist/number/refined-number-utils.mjs +91 -20
- package/dist/number/refined-number-utils.mjs.map +1 -1
- package/dist/object/object.d.mts +126 -208
- package/dist/object/object.d.mts.map +1 -1
- package/dist/object/object.mjs +68 -102
- package/dist/object/object.mjs.map +1 -1
- package/dist/others/cast-mutable.d.mts +12 -88
- package/dist/others/cast-mutable.d.mts.map +1 -1
- package/dist/others/cast-mutable.mjs +13 -89
- package/dist/others/cast-mutable.mjs.map +1 -1
- package/dist/others/cast-readonly.d.mts +12 -168
- package/dist/others/cast-readonly.d.mts.map +1 -1
- package/dist/others/cast-readonly.mjs +13 -169
- package/dist/others/cast-readonly.mjs.map +1 -1
- package/dist/others/if-then.d.mts +6 -83
- package/dist/others/if-then.d.mts.map +1 -1
- package/dist/others/if-then.mjs +6 -83
- package/dist/others/if-then.mjs.map +1 -1
- package/dist/others/map-nullable.d.mts +12 -136
- package/dist/others/map-nullable.d.mts.map +1 -1
- package/dist/others/map-nullable.mjs.map +1 -1
- package/dist/others/memoize-function.d.mts +14 -157
- package/dist/others/memoize-function.d.mts.map +1 -1
- package/dist/others/memoize-function.mjs +14 -157
- package/dist/others/memoize-function.mjs.map +1 -1
- package/dist/others/tuple.d.mts +33 -151
- package/dist/others/tuple.d.mts.map +1 -1
- package/dist/others/tuple.mjs +33 -151
- package/dist/others/tuple.mjs.map +1 -1
- package/dist/others/unknown-to-string.d.mts +11 -125
- package/dist/others/unknown-to-string.d.mts.map +1 -1
- package/dist/others/unknown-to-string.mjs +14 -127
- package/dist/others/unknown-to-string.mjs.map +1 -1
- package/dist/promise/promise.d.mts +33 -20
- package/dist/promise/promise.d.mts.map +1 -1
- package/dist/promise/promise.mjs +34 -21
- package/dist/promise/promise.mjs.map +1 -1
- package/dist/types.d.mts +1 -1
- package/package.json +54 -50
- package/src/array/impl/array-utils-creation.mts +192 -0
- package/src/array/{array-utils-creation.test.mts → impl/array-utils-creation.test.mts} +121 -72
- package/src/array/impl/array-utils-element-access.mts +115 -0
- package/src/array/impl/array-utils-element-access.test.mts +151 -0
- package/src/array/impl/array-utils-iterators.mts +79 -0
- package/src/array/impl/array-utils-iterators.test.mts +98 -0
- package/src/array/impl/array-utils-modification.mts +434 -0
- package/src/array/{array-utils-modification.test.mts → impl/array-utils-modification.test.mts} +41 -28
- package/src/array/{array-utils-overload-type-error.test.mts → impl/array-utils-overload-type-error.test.mts} +33 -33
- package/src/array/impl/array-utils-reducing-value.mts +551 -0
- package/src/array/{array-utils-reducing-value.test.mts → impl/array-utils-reducing-value.test.mts} +45 -50
- package/src/array/impl/array-utils-search.mts +509 -0
- package/src/array/impl/array-utils-search.test.mts +346 -0
- package/src/array/impl/array-utils-set-op.mts +166 -0
- package/src/array/{array-utils-set-op.test.mts → impl/array-utils-set-op.test.mts} +42 -35
- package/src/array/impl/array-utils-size.mts +30 -0
- package/src/array/impl/array-utils-size.test.mts +9 -0
- package/src/array/impl/array-utils-slice-clamped.mts +51 -0
- package/src/array/{array-utils-slice-clamped.test.mts → impl/array-utils-slice-clamped.test.mts} +12 -12
- package/src/array/impl/array-utils-slicing.mts +275 -0
- package/src/array/impl/array-utils-slicing.test.mts +158 -0
- package/src/array/impl/array-utils-transformation.mts +746 -0
- package/src/array/{array-utils-transformation.test.mts → impl/array-utils-transformation.test.mts} +662 -889
- package/src/array/impl/array-utils-validation.mts +241 -0
- package/src/array/{array-utils-validation.test.mts → impl/array-utils-validation.test.mts} +194 -107
- package/src/array/{array.test.mts → impl/array.test.mts} +2 -2
- package/src/array/impl/index.mts +12 -0
- package/src/array/index.mts +1 -1
- package/src/collections/imap-mapped.mts +99 -265
- package/src/collections/imap.mts +477 -174
- package/src/collections/imap.test.mts +12 -19
- package/src/collections/iset-mapped.mts +892 -358
- package/src/collections/iset.mts +429 -213
- package/src/collections/queue.mts +174 -200
- package/src/collections/stack.mts +172 -245
- package/src/collections/stack.test.mts +9 -1
- package/src/entry-point.mts +2 -0
- package/src/expect-type.mts +43 -172
- package/src/functional/match.mts +35 -145
- package/src/functional/optional.mts +285 -163
- package/src/functional/optional.test.mts +4 -1
- package/src/functional/pipe.mts +60 -113
- package/src/functional/result.mts +452 -351
- package/src/functional/result.test.mts +9 -2
- package/src/globals.d.mts +12 -5
- package/src/guard/has-key.mts +23 -74
- package/src/guard/is-non-empty-string.mts +20 -87
- package/src/guard/is-non-null-object.mts +14 -84
- package/src/guard/is-non-null-object.test.mts +1 -1
- package/src/guard/is-primitive.mts +13 -126
- package/src/guard/is-primitive.test.mts +1 -1
- package/src/guard/is-record.mts +21 -132
- package/src/guard/is-record.test.mts +0 -1
- package/src/guard/is-type.mts +201 -238
- package/src/guard/is-type.test.mts +7 -7
- package/src/guard/key-is-in.mts +22 -139
- package/src/index.mts +0 -1
- package/src/iterator/range.mts +29 -62
- package/src/json/json.mts +202 -134
- package/src/json/json.test.mts +1 -3
- package/src/number/branded-types/finite-number.mts +27 -159
- package/src/number/branded-types/int.mts +122 -120
- package/src/number/branded-types/int16.mts +22 -30
- package/src/number/branded-types/int16.test.mts +24 -24
- package/src/number/branded-types/int32.mts +22 -31
- package/src/number/branded-types/int32.test.mts +39 -39
- package/src/number/branded-types/non-negative-finite-number.mts +31 -39
- package/src/number/branded-types/non-negative-int16.mts +24 -34
- package/src/number/branded-types/non-negative-int16.test.mts +16 -16
- package/src/number/branded-types/non-negative-int32.mts +26 -35
- package/src/number/branded-types/non-negative-int32.test.mts +30 -30
- package/src/number/branded-types/non-zero-finite-number.mts +25 -40
- package/src/number/branded-types/non-zero-int.mts +15 -30
- package/src/number/branded-types/non-zero-int16.mts +27 -35
- package/src/number/branded-types/non-zero-int16.test.mts +26 -26
- package/src/number/branded-types/non-zero-int32.mts +29 -36
- package/src/number/branded-types/non-zero-int32.test.mts +45 -42
- package/src/number/branded-types/non-zero-safe-int.mts +39 -40
- package/src/number/branded-types/non-zero-uint16.mts +24 -35
- package/src/number/branded-types/non-zero-uint16.test.mts +16 -16
- package/src/number/branded-types/non-zero-uint32.mts +24 -35
- package/src/number/branded-types/non-zero-uint32.test.mts +28 -28
- package/src/number/branded-types/positive-finite-number.mts +29 -43
- package/src/number/branded-types/positive-int.mts +134 -124
- package/src/number/branded-types/positive-int16.mts +24 -35
- package/src/number/branded-types/positive-int16.test.mts +14 -14
- package/src/number/branded-types/positive-int32.mts +24 -35
- package/src/number/branded-types/positive-int32.test.mts +26 -26
- package/src/number/branded-types/positive-safe-int.mts +160 -34
- package/src/number/branded-types/positive-uint16.mts +24 -35
- package/src/number/branded-types/positive-uint16.test.mts +16 -16
- package/src/number/branded-types/positive-uint32.mts +26 -36
- package/src/number/branded-types/positive-uint32.test.mts +31 -28
- package/src/number/branded-types/safe-int.mts +142 -101
- package/src/number/branded-types/safe-uint.mts +25 -34
- package/src/number/branded-types/uint.mts +121 -30
- package/src/number/branded-types/uint16.mts +26 -34
- package/src/number/branded-types/uint16.test.mts +16 -16
- package/src/number/branded-types/uint32.mts +26 -68
- package/src/number/branded-types/uint32.test.mts +28 -28
- package/src/number/enum/int8.mts +39 -170
- package/src/number/enum/uint8.mts +46 -155
- package/src/number/num.mts +157 -212
- package/src/number/num.test.mts +4 -4
- package/src/number/refined-number-utils.mts +109 -26
- package/src/object/object.mts +130 -212
- package/src/object/object.test.mts +29 -0
- package/src/others/cast-mutable.mts +13 -89
- package/src/others/cast-mutable.test.mts +80 -0
- package/src/others/cast-readonly.mts +13 -169
- package/src/others/if-then.mts +6 -83
- package/src/others/map-nullable.mts +12 -136
- package/src/others/map-nullable.test.mts +6 -6
- package/src/others/memoize-function.mts +14 -157
- package/src/others/tuple.mts +33 -151
- package/src/others/unknown-to-string.mts +15 -127
- package/src/others/unknown-to-string.test.mts +14 -2
- package/src/promise/promise.mts +34 -21
- package/src/promise/promise.test.mts +43 -0
- package/dist/array/array-utils.d.mts +0 -2956
- package/dist/array/array-utils.d.mts.map +0 -1
- package/dist/array/array-utils.mjs +0 -1838
- package/dist/array/array-utils.mjs.map +0 -1
- package/src/array/array-utils-search.test.mts +0 -169
- package/src/array/array-utils-slicing.test.mts +0 -274
- package/src/array/array-utils.mts +0 -4834
|
@@ -1,84 +1,170 @@
|
|
|
1
1
|
import { asUint32 } from '../number/index.mjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Interface for an immutable set with custom element mapping and
|
|
4
|
+
* Interface for an immutable set with custom element mapping and membership
|
|
5
|
+
* testing.
|
|
5
6
|
*
|
|
6
|
-
* ISetMapped allows you to use complex objects as set elements by providing
|
|
7
|
-
* that convert between your custom element type `K`
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* ISetMapped allows you to use complex objects as set elements by providing
|
|
8
|
+
* transformation functions that convert between your custom element type `K`
|
|
9
|
+
* and a primitive `MapSetKeyType` `KM` that can be efficiently stored in
|
|
10
|
+
* JavaScript's native Set. This enables set operations on complex elements
|
|
11
|
+
* while maintaining type safety and immutability.
|
|
10
12
|
*
|
|
11
13
|
* **Key Features:**
|
|
12
|
-
*
|
|
13
|
-
* - **
|
|
14
|
+
*
|
|
15
|
+
* - **Custom Element Types**: Use any type as set elements by providing
|
|
16
|
+
* `toKey`/`fromKey` functions
|
|
14
17
|
* - **Immutable**: All operations return new instances, preserving immutability
|
|
15
|
-
* - **Set Operations**: Full support for union, intersection, difference,
|
|
18
|
+
* - **Set Operations**: Full support for union, intersection, difference,
|
|
19
|
+
* subset/superset checks
|
|
16
20
|
* - **Type Safe**: Full TypeScript support with generic element types
|
|
17
21
|
*
|
|
18
22
|
* **Performance Characteristics:**
|
|
19
|
-
*
|
|
20
|
-
* -
|
|
23
|
+
*
|
|
24
|
+
* - has: O(1) average case (plus element transformation overhead)
|
|
25
|
+
* - add/delete: O(n) due to copying for immutability (plus element
|
|
26
|
+
* transformation overhead)
|
|
27
|
+
* - set operations (union, intersection, difference): O(n)
|
|
21
28
|
* - map/filter operations: O(n)
|
|
22
|
-
* -
|
|
29
|
+
* - iteration: O(n) (plus element transformation overhead)
|
|
23
30
|
*
|
|
24
31
|
* @template K The type of the custom elements in the set.
|
|
25
32
|
* @template KM The type of the mapped primitive keys (string, number, etc.).
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* ```typescript
|
|
29
|
-
* // Example with complex object elements
|
|
30
|
-
* type User = { id: number; department: string; email: string };
|
|
31
|
-
*
|
|
32
|
-
* // Define transformation functions
|
|
33
|
-
* const userToKey = (user: User): string => `${user.department}:${user.id}`;
|
|
34
|
-
* const keyToUser = (key: string): User => {
|
|
35
|
-
* const [department, idStr] = key.split(':');
|
|
36
|
-
* // In practice, you might fetch from a cache or reconstruct more robustly
|
|
37
|
-
* return { id: Number(idStr), department, email: `user${idStr}@${department}.com` };
|
|
38
|
-
* };
|
|
39
|
-
*
|
|
40
|
-
* declare const activeUsers: ISetMapped<User, string>;
|
|
41
|
-
*
|
|
42
|
-
* // All operations work with the complex element type
|
|
43
|
-
* const user: User = { id: 123, department: "engineering", email: "alice@engineering.com" };
|
|
44
|
-
* const hasUser = activeUsers.has(user); // O(1)
|
|
45
|
-
* const withNewUser = activeUsers.add(user); // O(1) - returns new ISetMapped
|
|
46
|
-
* const withoutUser = activeUsers.delete(user); // O(1) - returns new ISetMapped
|
|
47
|
-
* ```
|
|
48
33
|
*/
|
|
49
34
|
type ISetMappedInterface<K, KM extends MapSetKeyType> = Readonly<{
|
|
50
35
|
/**
|
|
51
36
|
* Creates a new ISetMapped instance.
|
|
37
|
+
*
|
|
52
38
|
* @param iterable An iterable of elements.
|
|
53
39
|
* @param toKey A function that converts an element of type `K` to `KM`.
|
|
54
|
-
* @param fromKey A function that converts a mapped key of type `KM` back to
|
|
40
|
+
* @param fromKey A function that converts a mapped key of type `KM` back to
|
|
41
|
+
* `K`.
|
|
55
42
|
*/
|
|
56
43
|
new (iterable: Iterable<K>, toKey: (a: K) => KM, fromKey: (k: KM) => K): void;
|
|
57
44
|
|
|
58
45
|
// Getting information
|
|
59
|
-
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* The number of elements in the set.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
*
|
|
52
|
+
* ```ts
|
|
53
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
54
|
+
*
|
|
55
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
56
|
+
*
|
|
57
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
58
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
59
|
+
*
|
|
60
|
+
* const points: readonly Point[] = [
|
|
61
|
+
* { x: 1, tag: 'a' },
|
|
62
|
+
* { x: 2, tag: 'b' },
|
|
63
|
+
* ];
|
|
64
|
+
*
|
|
65
|
+
* const set = ISetMapped.create<Point, string>(points, toKey, fromKey);
|
|
66
|
+
*
|
|
67
|
+
* assert(set.size === 2);
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
60
70
|
size: SizeType.Arr;
|
|
61
71
|
|
|
62
|
-
/**
|
|
72
|
+
/**
|
|
73
|
+
* Checks if the set is empty.
|
|
74
|
+
*
|
|
75
|
+
* @example
|
|
76
|
+
*
|
|
77
|
+
* ```ts
|
|
78
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
79
|
+
*
|
|
80
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
81
|
+
*
|
|
82
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
83
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
84
|
+
*
|
|
85
|
+
* const empty = ISetMapped.create<Point, string>([], toKey, fromKey);
|
|
86
|
+
* const points = ISetMapped.create<Point, string>(
|
|
87
|
+
* [{ x: 1, tag: 'a' }],
|
|
88
|
+
* toKey,
|
|
89
|
+
* fromKey,
|
|
90
|
+
* );
|
|
91
|
+
*
|
|
92
|
+
* assert.ok(empty.isEmpty);
|
|
93
|
+
* assert.notOk(points.isEmpty);
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
63
96
|
isEmpty: boolean;
|
|
64
97
|
|
|
65
98
|
/**
|
|
66
99
|
* Checks if an element exists in the set.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
*
|
|
103
|
+
* ```ts
|
|
104
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
105
|
+
*
|
|
106
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
107
|
+
*
|
|
108
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
109
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
110
|
+
*
|
|
111
|
+
* const set = ISetMapped.create<Point, string>(
|
|
112
|
+
* [{ x: 1, tag: 'a' }],
|
|
113
|
+
* toKey,
|
|
114
|
+
* fromKey,
|
|
115
|
+
* );
|
|
116
|
+
*
|
|
117
|
+
* assert.ok(set.has({ x: 1, tag: 'a' }));
|
|
118
|
+
* assert.notOk(set.has({ x: 2, tag: 'b' }));
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
67
121
|
* @param key The element to check.
|
|
68
122
|
* @returns `true` if the element exists, `false` otherwise.
|
|
69
123
|
*/
|
|
70
124
|
has: (key: K) => boolean;
|
|
71
125
|
|
|
72
126
|
// Reducing a value
|
|
127
|
+
|
|
73
128
|
/**
|
|
74
129
|
* Checks if all elements in the set satisfy a predicate.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
*
|
|
133
|
+
* ```ts
|
|
134
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
135
|
+
*
|
|
136
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
137
|
+
*
|
|
138
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
139
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
140
|
+
*
|
|
141
|
+
* const set = ISetMapped.create<Point, string>(
|
|
142
|
+
* [
|
|
143
|
+
* { x: 2, tag: 'even' },
|
|
144
|
+
* { x: 4, tag: 'even' },
|
|
145
|
+
* ],
|
|
146
|
+
* toKey,
|
|
147
|
+
* fromKey,
|
|
148
|
+
* );
|
|
149
|
+
*
|
|
150
|
+
* const allEven = set.every((point) => point.x % 2 === 0);
|
|
151
|
+
* const narrowed = set.every(
|
|
152
|
+
* (point): point is Readonly<{ x: 2 | 4; tag: 'even' }> => point.x % 2 === 0,
|
|
153
|
+
* );
|
|
154
|
+
*
|
|
155
|
+
* assert.ok(allEven);
|
|
156
|
+
* assert.ok(narrowed);
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
75
159
|
* @param predicate A function to test each element.
|
|
76
160
|
* @returns `true` if all elements satisfy the predicate, `false` otherwise.
|
|
77
161
|
*/
|
|
78
162
|
every: ((predicate: (key: K) => boolean) => boolean) &
|
|
79
163
|
/**
|
|
80
|
-
* Checks if all elements in the set satisfy a type predicate.
|
|
81
|
-
*
|
|
164
|
+
* Checks if all elements in the set satisfy a type predicate. Narrows the
|
|
165
|
+
* type of elements in the set if the predicate returns true for all
|
|
166
|
+
* elements.
|
|
167
|
+
*
|
|
82
168
|
* @template L The narrowed type of the elements.
|
|
83
169
|
* @param predicate A type predicate function.
|
|
84
170
|
* @returns `true` if all elements satisfy the predicate, `false` otherwise.
|
|
@@ -86,28 +172,150 @@ type ISetMappedInterface<K, KM extends MapSetKeyType> = Readonly<{
|
|
|
86
172
|
(<L extends K>(
|
|
87
173
|
predicate: (key: K) => key is L,
|
|
88
174
|
) => this is ISetMapped<L, KM>);
|
|
175
|
+
|
|
89
176
|
/**
|
|
90
177
|
* Checks if at least one element in the set satisfies a predicate.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
*
|
|
181
|
+
* ```ts
|
|
182
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
183
|
+
*
|
|
184
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
185
|
+
*
|
|
186
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
187
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
188
|
+
*
|
|
189
|
+
* const set = ISetMapped.create<Point, string>(
|
|
190
|
+
* [
|
|
191
|
+
* { x: 1, tag: 'a' },
|
|
192
|
+
* { x: 5, tag: 'b' },
|
|
193
|
+
* ],
|
|
194
|
+
* toKey,
|
|
195
|
+
* fromKey,
|
|
196
|
+
* );
|
|
197
|
+
*
|
|
198
|
+
* assert.ok(set.some((point) => point.x > 4));
|
|
199
|
+
* assert.notOk(set.some((point) => point.x > 10));
|
|
200
|
+
* ```
|
|
201
|
+
*
|
|
91
202
|
* @param predicate A function to test each element.
|
|
92
|
-
* @returns `true` if at least one element satisfies the predicate, `false`
|
|
203
|
+
* @returns `true` if at least one element satisfies the predicate, `false`
|
|
204
|
+
* otherwise.
|
|
93
205
|
*/
|
|
94
206
|
some: (predicate: (key: K) => boolean) => boolean;
|
|
95
207
|
|
|
96
208
|
// Mutation
|
|
209
|
+
|
|
97
210
|
/**
|
|
98
211
|
* Adds an element to the set.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
*
|
|
215
|
+
* ```ts
|
|
216
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
217
|
+
*
|
|
218
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
219
|
+
*
|
|
220
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
221
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
222
|
+
*
|
|
223
|
+
* const base = ISetMapped.create<Point, string>(
|
|
224
|
+
* [{ x: 1, tag: 'a' }],
|
|
225
|
+
* toKey,
|
|
226
|
+
* fromKey,
|
|
227
|
+
* );
|
|
228
|
+
*
|
|
229
|
+
* const withNew = base.add({ x: 2, tag: 'b' });
|
|
230
|
+
* const unchanged = base.add({ x: 1, tag: 'a' });
|
|
231
|
+
*
|
|
232
|
+
* assert.deepStrictEqual(Array.from(withNew), [
|
|
233
|
+
* { x: 1, tag: 'a' },
|
|
234
|
+
* { x: 2, tag: 'b' },
|
|
235
|
+
* ]);
|
|
236
|
+
* assert(unchanged === base);
|
|
237
|
+
* ```
|
|
238
|
+
*
|
|
99
239
|
* @param key The element to add.
|
|
100
240
|
* @returns A new ISetMapped instance with the element added.
|
|
101
241
|
*/
|
|
102
242
|
add: (key: K) => ISetMapped<K, KM>;
|
|
243
|
+
|
|
103
244
|
/**
|
|
104
245
|
* Deletes an element from the set.
|
|
246
|
+
*
|
|
247
|
+
* @example
|
|
248
|
+
*
|
|
249
|
+
* ```ts
|
|
250
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
251
|
+
*
|
|
252
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
253
|
+
*
|
|
254
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
255
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
256
|
+
*
|
|
257
|
+
* const base = ISetMapped.create<Point, string>(
|
|
258
|
+
* [
|
|
259
|
+
* { x: 1, tag: 'a' },
|
|
260
|
+
* { x: 2, tag: 'b' },
|
|
261
|
+
* ],
|
|
262
|
+
* toKey,
|
|
263
|
+
* fromKey,
|
|
264
|
+
* );
|
|
265
|
+
*
|
|
266
|
+
* const withoutSecond = base.delete({ x: 2, tag: 'b' });
|
|
267
|
+
* const unchanged = base.delete({ x: 3, tag: 'c' });
|
|
268
|
+
*
|
|
269
|
+
* assert.deepStrictEqual(Array.from(withoutSecond), [{ x: 1, tag: 'a' }]);
|
|
270
|
+
* assert(unchanged === base);
|
|
271
|
+
* ```
|
|
272
|
+
*
|
|
105
273
|
* @param key The element to delete.
|
|
106
274
|
* @returns A new ISetMapped instance without the specified element.
|
|
107
275
|
*/
|
|
108
276
|
delete: (key: K) => ISetMapped<K, KM>;
|
|
277
|
+
|
|
109
278
|
/**
|
|
110
279
|
* Applies a series of mutations to the set.
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
*
|
|
283
|
+
* ```ts
|
|
284
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
285
|
+
*
|
|
286
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
287
|
+
*
|
|
288
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
289
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
290
|
+
*
|
|
291
|
+
* const base = ISetMapped.create<Point, string>(
|
|
292
|
+
* [
|
|
293
|
+
* { x: 1, tag: 'a' },
|
|
294
|
+
* { x: 2, tag: 'b' },
|
|
295
|
+
* ],
|
|
296
|
+
* toKey,
|
|
297
|
+
* fromKey,
|
|
298
|
+
* );
|
|
299
|
+
*
|
|
300
|
+
* const actions: readonly Readonly<
|
|
301
|
+
* { type: 'add'; key: Point } | { type: 'delete'; key: Point }
|
|
302
|
+
* >[] = [
|
|
303
|
+
* { type: 'add', key: { x: 3, tag: 'c' } },
|
|
304
|
+
* { type: 'delete', key: { x: 1, tag: 'a' } },
|
|
305
|
+
* ];
|
|
306
|
+
*
|
|
307
|
+
* const mutated = base.withMutations(actions);
|
|
308
|
+
*
|
|
309
|
+
* assert.deepStrictEqual(Array.from(mutated), [
|
|
310
|
+
* { x: 2, tag: 'b' },
|
|
311
|
+
* { x: 3, tag: 'c' },
|
|
312
|
+
* ]);
|
|
313
|
+
* assert.deepStrictEqual(Array.from(base), [
|
|
314
|
+
* { x: 1, tag: 'a' },
|
|
315
|
+
* { x: 2, tag: 'b' },
|
|
316
|
+
* ]);
|
|
317
|
+
* ```
|
|
318
|
+
*
|
|
111
319
|
* @param actions An array of mutation actions (add or delete).
|
|
112
320
|
* @returns A new ISetMapped instance with all mutations applied.
|
|
113
321
|
*/
|
|
@@ -118,114 +326,538 @@ type ISetMappedInterface<K, KM extends MapSetKeyType> = Readonly<{
|
|
|
118
326
|
) => ISetMapped<K, KM>;
|
|
119
327
|
|
|
120
328
|
// Sequence algorithms
|
|
329
|
+
|
|
121
330
|
/**
|
|
122
|
-
* Maps the elements of the set to new elements.
|
|
123
|
-
*
|
|
124
|
-
*
|
|
331
|
+
* Maps the elements of the set to new elements. Note: The element type `K`
|
|
332
|
+
* cannot be changed because `toKey` and `fromKey` would become unusable if
|
|
333
|
+
* the mapped type `KM` changes.
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
*
|
|
337
|
+
* ```ts
|
|
338
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
339
|
+
*
|
|
340
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
341
|
+
*
|
|
342
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
343
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
344
|
+
*
|
|
345
|
+
* const set = ISetMapped.create<Point, string>(
|
|
346
|
+
* [
|
|
347
|
+
* { x: 1, tag: 'a' },
|
|
348
|
+
* { x: 2, tag: 'b' },
|
|
349
|
+
* ],
|
|
350
|
+
* toKey,
|
|
351
|
+
* fromKey,
|
|
352
|
+
* );
|
|
353
|
+
*
|
|
354
|
+
* const shifted = set.map((point) => ({
|
|
355
|
+
* x: point.x + 10,
|
|
356
|
+
* tag: point.tag.toUpperCase(),
|
|
357
|
+
* }));
|
|
358
|
+
*
|
|
359
|
+
* assert.deepStrictEqual(Array.from(shifted), [
|
|
360
|
+
* { x: 11, tag: 'A' },
|
|
361
|
+
* { x: 12, tag: 'B' },
|
|
362
|
+
* ]);
|
|
363
|
+
* ```
|
|
364
|
+
*
|
|
365
|
+
* @param mapFn A function that maps an element to a new element of the same
|
|
366
|
+
* type `K`.
|
|
125
367
|
* @returns A new ISetMapped instance with mapped elements.
|
|
126
368
|
*/
|
|
127
369
|
map: (mapFn: (key: K) => K) => ISetMapped<K, KM>;
|
|
128
370
|
|
|
129
371
|
/**
|
|
130
372
|
* Filters the elements of the set based on a predicate.
|
|
373
|
+
*
|
|
374
|
+
* @example
|
|
375
|
+
*
|
|
376
|
+
* ```ts
|
|
377
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
378
|
+
*
|
|
379
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
380
|
+
*
|
|
381
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
382
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
383
|
+
*
|
|
384
|
+
* const set = ISetMapped.create<Point, string>(
|
|
385
|
+
* [
|
|
386
|
+
* { x: 1, tag: 'a' },
|
|
387
|
+
* { x: 2, tag: 'b' },
|
|
388
|
+
* { x: 3, tag: 'c' },
|
|
389
|
+
* ],
|
|
390
|
+
* toKey,
|
|
391
|
+
* fromKey,
|
|
392
|
+
* );
|
|
393
|
+
*
|
|
394
|
+
* const evenPoints = set.filter((point) => point.x % 2 === 0);
|
|
395
|
+
*
|
|
396
|
+
* assert.deepStrictEqual(Array.from(evenPoints), [{ x: 2, tag: 'b' }]);
|
|
397
|
+
* ```
|
|
398
|
+
*
|
|
131
399
|
* @param predicate A function to test each element.
|
|
132
|
-
* @returns A new ISetMapped instance with elements that satisfy the
|
|
400
|
+
* @returns A new ISetMapped instance with elements that satisfy the
|
|
401
|
+
* predicate.
|
|
133
402
|
*/
|
|
134
403
|
filter: (predicate: (value: K) => boolean) => ISetMapped<K, KM>;
|
|
135
404
|
|
|
136
405
|
/**
|
|
137
|
-
* Filters the elements of the set by excluding elements for which the
|
|
406
|
+
* Filters the elements of the set by excluding elements for which the
|
|
407
|
+
* predicate returns true.
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
*
|
|
411
|
+
* ```ts
|
|
412
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
413
|
+
*
|
|
414
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
415
|
+
*
|
|
416
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
417
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
418
|
+
*
|
|
419
|
+
* const set = ISetMapped.create<Point, string>(
|
|
420
|
+
* [
|
|
421
|
+
* { x: 1, tag: 'a' },
|
|
422
|
+
* { x: 2, tag: 'b' },
|
|
423
|
+
* ],
|
|
424
|
+
* toKey,
|
|
425
|
+
* fromKey,
|
|
426
|
+
* );
|
|
427
|
+
*
|
|
428
|
+
* const withoutEven = set.filterNot((point) => point.x % 2 === 0);
|
|
429
|
+
*
|
|
430
|
+
* assert.deepStrictEqual(Array.from(withoutEven), [{ x: 1, tag: 'a' }]);
|
|
431
|
+
* ```
|
|
432
|
+
*
|
|
138
433
|
* @param predicate A function to test each element.
|
|
139
|
-
* @returns A new ISetMapped instance with elements for which the predicate
|
|
434
|
+
* @returns A new ISetMapped instance with elements for which the predicate
|
|
435
|
+
* returned `false`.
|
|
140
436
|
*/
|
|
141
437
|
filterNot: (predicate: (key: K) => boolean) => ISetMapped<K, KM>;
|
|
142
438
|
|
|
143
439
|
// Side effects
|
|
440
|
+
|
|
144
441
|
/**
|
|
145
442
|
* Executes a callback function for each element in the set.
|
|
443
|
+
*
|
|
444
|
+
* @example
|
|
445
|
+
*
|
|
446
|
+
* ```ts
|
|
447
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
448
|
+
*
|
|
449
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
450
|
+
*
|
|
451
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
452
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
453
|
+
*
|
|
454
|
+
* const set = ISetMapped.create<Point, string>(
|
|
455
|
+
* [
|
|
456
|
+
* { x: 1, tag: 'a' },
|
|
457
|
+
* { x: 2, tag: 'b' },
|
|
458
|
+
* ],
|
|
459
|
+
* toKey,
|
|
460
|
+
* fromKey,
|
|
461
|
+
* );
|
|
462
|
+
*
|
|
463
|
+
* const collected: Point[] = [];
|
|
464
|
+
* for (const point of set) {
|
|
465
|
+
* collected.push(point);
|
|
466
|
+
* }
|
|
467
|
+
*
|
|
468
|
+
* assert.deepStrictEqual(collected, [
|
|
469
|
+
* { x: 1, tag: 'a' },
|
|
470
|
+
* { x: 2, tag: 'b' },
|
|
471
|
+
* ]);
|
|
472
|
+
* ```
|
|
473
|
+
*
|
|
146
474
|
* @param callbackfn A function to execute for each element.
|
|
147
475
|
*/
|
|
148
476
|
forEach: (callbackfn: (key: K) => void) => void;
|
|
149
477
|
|
|
150
478
|
// Comparison
|
|
479
|
+
|
|
151
480
|
/**
|
|
152
481
|
* Checks if this set is a subset of another set.
|
|
482
|
+
*
|
|
483
|
+
* @example
|
|
484
|
+
*
|
|
485
|
+
* ```ts
|
|
486
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
487
|
+
*
|
|
488
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
489
|
+
*
|
|
490
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
491
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
492
|
+
*
|
|
493
|
+
* const subset = ISetMapped.create<Point, string>(
|
|
494
|
+
* [{ x: 1, tag: 'a' }],
|
|
495
|
+
* toKey,
|
|
496
|
+
* fromKey,
|
|
497
|
+
* );
|
|
498
|
+
* const superset = ISetMapped.create<Point, string>(
|
|
499
|
+
* [
|
|
500
|
+
* { x: 1, tag: 'a' },
|
|
501
|
+
* { x: 2, tag: 'b' },
|
|
502
|
+
* ],
|
|
503
|
+
* toKey,
|
|
504
|
+
* fromKey,
|
|
505
|
+
* );
|
|
506
|
+
*
|
|
507
|
+
* assert.ok(subset.isSubsetOf(superset));
|
|
508
|
+
* assert.notOk(superset.isSubsetOf(subset));
|
|
509
|
+
* ```
|
|
510
|
+
*
|
|
153
511
|
* @param set The other set.
|
|
154
|
-
* @returns `true` if this set is a subset of the other set, `false`
|
|
512
|
+
* @returns `true` if this set is a subset of the other set, `false`
|
|
513
|
+
* otherwise.
|
|
155
514
|
*/
|
|
156
515
|
isSubsetOf: (set: ISetMapped<K, KM>) => boolean;
|
|
516
|
+
|
|
157
517
|
/**
|
|
158
518
|
* Checks if this set is a superset of another set.
|
|
519
|
+
*
|
|
520
|
+
* @example
|
|
521
|
+
*
|
|
522
|
+
* ```ts
|
|
523
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
524
|
+
*
|
|
525
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
526
|
+
*
|
|
527
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
528
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
529
|
+
*
|
|
530
|
+
* const superset = ISetMapped.create<Point, string>(
|
|
531
|
+
* [
|
|
532
|
+
* { x: 1, tag: 'a' },
|
|
533
|
+
* { x: 2, tag: 'b' },
|
|
534
|
+
* ],
|
|
535
|
+
* toKey,
|
|
536
|
+
* fromKey,
|
|
537
|
+
* );
|
|
538
|
+
* const subset = ISetMapped.create<Point, string>(
|
|
539
|
+
* [{ x: 2, tag: 'b' }],
|
|
540
|
+
* toKey,
|
|
541
|
+
* fromKey,
|
|
542
|
+
* );
|
|
543
|
+
*
|
|
544
|
+
* assert.ok(superset.isSupersetOf(subset));
|
|
545
|
+
* assert.notOk(subset.isSupersetOf(superset));
|
|
546
|
+
* ```
|
|
547
|
+
*
|
|
159
548
|
* @param set The other set.
|
|
160
|
-
* @returns `true` if this set is a superset of the other set, `false`
|
|
549
|
+
* @returns `true` if this set is a superset of the other set, `false`
|
|
550
|
+
* otherwise.
|
|
161
551
|
*/
|
|
162
552
|
isSupersetOf: (set: ISetMapped<K, KM>) => boolean;
|
|
553
|
+
|
|
163
554
|
/**
|
|
164
|
-
* Returns a new set with elements that are in this set but not in another
|
|
555
|
+
* Returns a new set with elements that are in this set but not in another
|
|
556
|
+
* set.
|
|
557
|
+
*
|
|
558
|
+
* @example
|
|
559
|
+
*
|
|
560
|
+
* ```ts
|
|
561
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
562
|
+
*
|
|
563
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
564
|
+
*
|
|
565
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
566
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
567
|
+
*
|
|
568
|
+
* const left = ISetMapped.create<Point, string>(
|
|
569
|
+
* [
|
|
570
|
+
* { x: 1, tag: 'a' },
|
|
571
|
+
* { x: 2, tag: 'b' },
|
|
572
|
+
* { x: 3, tag: 'c' },
|
|
573
|
+
* ],
|
|
574
|
+
* toKey,
|
|
575
|
+
* fromKey,
|
|
576
|
+
* );
|
|
577
|
+
* const right = ISetMapped.create<Point, string>(
|
|
578
|
+
* [{ x: 2, tag: 'b' }],
|
|
579
|
+
* toKey,
|
|
580
|
+
* fromKey,
|
|
581
|
+
* );
|
|
582
|
+
*
|
|
583
|
+
* const difference = left.subtract(right);
|
|
584
|
+
*
|
|
585
|
+
* assert.deepStrictEqual(Array.from(difference), [
|
|
586
|
+
* { x: 1, tag: 'a' },
|
|
587
|
+
* { x: 3, tag: 'c' },
|
|
588
|
+
* ]);
|
|
589
|
+
* ```
|
|
590
|
+
*
|
|
165
591
|
* @param set The other set.
|
|
166
592
|
* @returns A new ISetMapped instance representing the set difference.
|
|
167
593
|
*/
|
|
168
594
|
subtract: (set: ISetMapped<K, KM>) => ISetMapped<K, KM>;
|
|
595
|
+
|
|
169
596
|
/**
|
|
170
|
-
* Returns a new set with elements that are common to both this set and
|
|
597
|
+
* Returns a new set with elements that are common to both this set and
|
|
598
|
+
* another set.
|
|
599
|
+
*
|
|
600
|
+
* @example
|
|
601
|
+
*
|
|
602
|
+
* ```ts
|
|
603
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
604
|
+
*
|
|
605
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
606
|
+
*
|
|
607
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
608
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
609
|
+
*
|
|
610
|
+
* const left = ISetMapped.create<Point, string>(
|
|
611
|
+
* [
|
|
612
|
+
* { x: 1, tag: 'a' },
|
|
613
|
+
* { x: 2, tag: 'b' },
|
|
614
|
+
* ],
|
|
615
|
+
* toKey,
|
|
616
|
+
* fromKey,
|
|
617
|
+
* );
|
|
618
|
+
* const right = ISetMapped.create<Point, string>(
|
|
619
|
+
* [{ x: 2, tag: 'b' }],
|
|
620
|
+
* toKey,
|
|
621
|
+
* fromKey,
|
|
622
|
+
* );
|
|
623
|
+
*
|
|
624
|
+
* const intersection = left.intersect(right);
|
|
625
|
+
*
|
|
626
|
+
* assert.deepStrictEqual(Array.from(intersection), [{ x: 2, tag: 'b' }]);
|
|
627
|
+
* ```
|
|
628
|
+
*
|
|
171
629
|
* @param set The other set.
|
|
172
630
|
* @returns A new ISetMapped instance representing the set intersection.
|
|
173
631
|
*/
|
|
174
632
|
intersect: (set: ISetMapped<K, KM>) => ISetMapped<K, KM>;
|
|
633
|
+
|
|
175
634
|
/**
|
|
176
635
|
* Returns a new set with all elements from both this set and another set.
|
|
636
|
+
*
|
|
637
|
+
* @example
|
|
638
|
+
*
|
|
639
|
+
* ```ts
|
|
640
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
641
|
+
*
|
|
642
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
643
|
+
*
|
|
644
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
645
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
646
|
+
*
|
|
647
|
+
* const left = ISetMapped.create<Point, string>(
|
|
648
|
+
* [{ x: 1, tag: 'a' }],
|
|
649
|
+
* toKey,
|
|
650
|
+
* fromKey,
|
|
651
|
+
* );
|
|
652
|
+
* const right = ISetMapped.create<Point, string>(
|
|
653
|
+
* [{ x: 2, tag: 'b' }],
|
|
654
|
+
* toKey,
|
|
655
|
+
* fromKey,
|
|
656
|
+
* );
|
|
657
|
+
*
|
|
658
|
+
* const combined = left.union(right);
|
|
659
|
+
*
|
|
660
|
+
* assert.deepStrictEqual(Array.from(combined), [
|
|
661
|
+
* { x: 1, tag: 'a' },
|
|
662
|
+
* { x: 2, tag: 'b' },
|
|
663
|
+
* ]);
|
|
664
|
+
* ```
|
|
665
|
+
*
|
|
177
666
|
* @param set The other set.
|
|
178
667
|
* @returns A new ISetMapped instance representing the set union.
|
|
179
668
|
*/
|
|
180
669
|
union: (set: ISetMapped<K, KM>) => ISetMapped<K, KM>;
|
|
181
670
|
|
|
182
671
|
// Iterators
|
|
672
|
+
|
|
183
673
|
/**
|
|
184
674
|
* Returns an iterator for the elements in the set (alias for values).
|
|
675
|
+
*
|
|
676
|
+
* @example
|
|
677
|
+
*
|
|
678
|
+
* ```ts
|
|
679
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
680
|
+
*
|
|
681
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
682
|
+
*
|
|
683
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
684
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
685
|
+
*
|
|
686
|
+
* const set = ISetMapped.create<Point, string>(
|
|
687
|
+
* [
|
|
688
|
+
* { x: 1, tag: 'a' },
|
|
689
|
+
* { x: 2, tag: 'b' },
|
|
690
|
+
* ],
|
|
691
|
+
* toKey,
|
|
692
|
+
* fromKey,
|
|
693
|
+
* );
|
|
694
|
+
*
|
|
695
|
+
* assert.deepStrictEqual(Array.from(set.keys()), [
|
|
696
|
+
* { x: 1, tag: 'a' },
|
|
697
|
+
* { x: 2, tag: 'b' },
|
|
698
|
+
* ]);
|
|
699
|
+
* ```
|
|
700
|
+
*
|
|
185
701
|
* @returns An iterable iterator of elements.
|
|
186
702
|
*/
|
|
187
703
|
keys: () => IterableIterator<K>;
|
|
704
|
+
|
|
188
705
|
/**
|
|
189
706
|
* Returns an iterator for the elements in the set.
|
|
707
|
+
*
|
|
708
|
+
* @example
|
|
709
|
+
*
|
|
710
|
+
* ```ts
|
|
711
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
712
|
+
*
|
|
713
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
714
|
+
*
|
|
715
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
716
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
717
|
+
*
|
|
718
|
+
* const set = ISetMapped.create<Point, string>(
|
|
719
|
+
* [
|
|
720
|
+
* { x: 1, tag: 'a' },
|
|
721
|
+
* { x: 2, tag: 'b' },
|
|
722
|
+
* ],
|
|
723
|
+
* toKey,
|
|
724
|
+
* fromKey,
|
|
725
|
+
* );
|
|
726
|
+
*
|
|
727
|
+
* assert.deepStrictEqual(Array.from(set.values()), [
|
|
728
|
+
* { x: 1, tag: 'a' },
|
|
729
|
+
* { x: 2, tag: 'b' },
|
|
730
|
+
* ]);
|
|
731
|
+
* ```
|
|
732
|
+
*
|
|
190
733
|
* @returns An iterable iterator of elements.
|
|
191
734
|
*/
|
|
192
735
|
values: () => IterableIterator<K>;
|
|
736
|
+
|
|
193
737
|
/**
|
|
194
738
|
* Returns an iterator for the entries (element-element pairs) in the set.
|
|
739
|
+
*
|
|
740
|
+
* @example
|
|
741
|
+
*
|
|
742
|
+
* ```ts
|
|
743
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
744
|
+
*
|
|
745
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
746
|
+
*
|
|
747
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
748
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
749
|
+
*
|
|
750
|
+
* const set = ISetMapped.create<Point, string>(
|
|
751
|
+
* [
|
|
752
|
+
* { x: 1, tag: 'a' },
|
|
753
|
+
* { x: 2, tag: 'b' },
|
|
754
|
+
* ],
|
|
755
|
+
* toKey,
|
|
756
|
+
* fromKey,
|
|
757
|
+
* );
|
|
758
|
+
*
|
|
759
|
+
* assert.deepStrictEqual(Array.from(set.entries()), [
|
|
760
|
+
* [
|
|
761
|
+
* { x: 1, tag: 'a' },
|
|
762
|
+
* { x: 1, tag: 'a' },
|
|
763
|
+
* ],
|
|
764
|
+
* [
|
|
765
|
+
* { x: 2, tag: 'b' },
|
|
766
|
+
* { x: 2, tag: 'b' },
|
|
767
|
+
* ],
|
|
768
|
+
* ]);
|
|
769
|
+
* ```
|
|
770
|
+
*
|
|
195
771
|
* @returns An iterable iterator of entries.
|
|
196
772
|
*/
|
|
197
773
|
entries: () => IterableIterator<readonly [K, K]>;
|
|
198
774
|
|
|
199
775
|
// Conversion
|
|
776
|
+
|
|
200
777
|
/**
|
|
201
778
|
* Converts the elements of the set to an array.
|
|
779
|
+
*
|
|
780
|
+
* @example
|
|
781
|
+
*
|
|
782
|
+
* ```ts
|
|
783
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
784
|
+
*
|
|
785
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
786
|
+
*
|
|
787
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
788
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
789
|
+
*
|
|
790
|
+
* const set = ISetMapped.create<Point, string>(
|
|
791
|
+
* [
|
|
792
|
+
* { x: 1, tag: 'a' },
|
|
793
|
+
* { x: 2, tag: 'b' },
|
|
794
|
+
* ],
|
|
795
|
+
* toKey,
|
|
796
|
+
* fromKey,
|
|
797
|
+
* );
|
|
798
|
+
*
|
|
799
|
+
* assert.deepStrictEqual(set.toArray(), [
|
|
800
|
+
* { x: 1, tag: 'a' },
|
|
801
|
+
* { x: 2, tag: 'b' },
|
|
802
|
+
* ]);
|
|
803
|
+
* ```
|
|
804
|
+
*
|
|
202
805
|
* @returns A readonly array of elements.
|
|
203
806
|
*/
|
|
204
807
|
toArray: () => readonly K[];
|
|
808
|
+
|
|
205
809
|
/**
|
|
206
810
|
* Returns the underlying readonly JavaScript Set of mapped keys.
|
|
811
|
+
*
|
|
812
|
+
* @example
|
|
813
|
+
*
|
|
814
|
+
* ```ts
|
|
815
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
816
|
+
*
|
|
817
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
818
|
+
*
|
|
819
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
820
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
821
|
+
*
|
|
822
|
+
* const set = ISetMapped.create<Point, string>(
|
|
823
|
+
* [{ x: 1, tag: 'a' }],
|
|
824
|
+
* toKey,
|
|
825
|
+
* fromKey,
|
|
826
|
+
* );
|
|
827
|
+
*
|
|
828
|
+
* const raw = set.toRawSet();
|
|
829
|
+
*
|
|
830
|
+
* assert.ok(is.set(raw));
|
|
831
|
+
* assert.ok(raw.has(toKey({ x: 1, tag: 'a' })));
|
|
832
|
+
* ```
|
|
833
|
+
*
|
|
207
834
|
* @returns The raw ReadonlySet instance.
|
|
208
835
|
*/
|
|
209
836
|
toRawSet: () => ReadonlySet<KM>;
|
|
210
837
|
}>;
|
|
211
838
|
|
|
212
839
|
/**
|
|
213
|
-
* Represents an immutable set with custom element transformation and
|
|
840
|
+
* Represents an immutable set with custom element transformation and
|
|
841
|
+
* high-performance operations.
|
|
214
842
|
*
|
|
215
|
-
* ISetMapped is a specialized persistent data structure that enables using
|
|
216
|
-
* while maintaining the performance benefits of
|
|
217
|
-
*
|
|
218
|
-
* that
|
|
843
|
+
* ISetMapped is a specialized persistent data structure that enables using
|
|
844
|
+
* complex objects as set elements while maintaining the performance benefits of
|
|
845
|
+
* JavaScript's native Set. It achieves this by requiring bidirectional
|
|
846
|
+
* transformation functions that convert between your custom element type and a
|
|
847
|
+
* primitive type that can be efficiently stored and compared for uniqueness.
|
|
219
848
|
*
|
|
220
849
|
* **Key Features:**
|
|
850
|
+
*
|
|
221
851
|
* - **Complex Elements**: Use objects, arrays, or any custom type as set elements
|
|
222
|
-
* - **High Performance**: O(1) operations through efficient element transformation
|
|
223
852
|
* - **Immutable**: All mutation operations return new instances
|
|
224
|
-
* - **Type Safe**: Full TypeScript support with compile-time element type
|
|
225
|
-
*
|
|
853
|
+
* - **Type Safe**: Full TypeScript support with compile-time element type
|
|
854
|
+
* checking
|
|
855
|
+
* - **Bidirectional**: Maintains ability to reconstruct original elements from
|
|
856
|
+
* mapped keys
|
|
226
857
|
* - **Set Algebra**: Complete support for mathematical set operations
|
|
227
858
|
*
|
|
228
859
|
* **Use Cases:**
|
|
860
|
+
*
|
|
229
861
|
* - Sets of entities with complex identifiers
|
|
230
862
|
* - Deduplication of objects based on specific properties
|
|
231
863
|
* - Performance-critical sets with non-primitive elements
|
|
@@ -233,175 +865,60 @@ type ISetMappedInterface<K, KM extends MapSetKeyType> = Readonly<{
|
|
|
233
865
|
*
|
|
234
866
|
* @template K The type of the custom elements in the set.
|
|
235
867
|
* @template KM The type of the mapped primitive keys (string, number, etc.).
|
|
236
|
-
*
|
|
237
|
-
* @example
|
|
238
|
-
* ```typescript
|
|
239
|
-
* // Example: User management with composite identity
|
|
240
|
-
* type User = { id: number; department: string; username: string; email: string };
|
|
241
|
-
*
|
|
242
|
-
* // Define bidirectional transformation functions
|
|
243
|
-
* const userToKey = (user: User): string => `${user.department}:${user.id}`;
|
|
244
|
-
* const keyToUser = (key: string): User => {
|
|
245
|
-
* const [department, idStr] = key.split(':');
|
|
246
|
-
* const id = Number(idStr);
|
|
247
|
-
* // In practice, this might fetch from a user service or cache
|
|
248
|
-
* return {
|
|
249
|
-
* id,
|
|
250
|
-
* department,
|
|
251
|
-
* username: `user${id}`,
|
|
252
|
-
* email: `user${id}@${department}.company.com`
|
|
253
|
-
* };
|
|
254
|
-
* };
|
|
255
|
-
*
|
|
256
|
-
* // Create a set with complex elements
|
|
257
|
-
* let activeUsers = ISetMapped.create<User, string>([], userToKey, keyToUser);
|
|
258
|
-
*
|
|
259
|
-
* // Use complex objects as elements naturally
|
|
260
|
-
* const alice: User = { id: 1, department: "engineering", username: "alice", email: "alice@engineering.company.com" };
|
|
261
|
-
* const bob: User = { id: 2, department: "marketing", username: "bob", email: "bob@marketing.company.com" };
|
|
262
|
-
* const charlie: User = { id: 3, department: "engineering", username: "charlie", email: "charlie@engineering.company.com" };
|
|
263
|
-
*
|
|
264
|
-
* activeUsers = activeUsers
|
|
265
|
-
* .add(alice)
|
|
266
|
-
* .add(bob)
|
|
267
|
-
* .add(charlie);
|
|
268
|
-
*
|
|
269
|
-
* // All operations work with the original element type
|
|
270
|
-
* console.log(activeUsers.has(alice)); // Output: true
|
|
271
|
-
* console.log(activeUsers.size); // Output: 3
|
|
272
|
-
*
|
|
273
|
-
* // Set operations preserve element types
|
|
274
|
-
* const engineeringUsers = ISetMapped.create<User, string>([alice, charlie], userToKey, keyToUser);
|
|
275
|
-
* const marketingUsers = ISetMapped.create<User, string>([bob], userToKey, keyToUser);
|
|
276
|
-
*
|
|
277
|
-
* const allUsers = ISetMapped.union(engineeringUsers, marketingUsers);
|
|
278
|
-
* const engineeringOnly = activeUsers.intersect(engineeringUsers);
|
|
279
|
-
*
|
|
280
|
-
* // Iteration preserves original element types
|
|
281
|
-
* for (const user of engineeringOnly) {
|
|
282
|
-
* console.log(`${user.username} works in ${user.department}`);
|
|
283
|
-
* }
|
|
284
|
-
* // Output:
|
|
285
|
-
* // alice works in engineering
|
|
286
|
-
* // charlie works in engineering
|
|
287
|
-
*
|
|
288
|
-
* // Functional transformations work seamlessly
|
|
289
|
-
* const updatedUsers = activeUsers.map(user => ({
|
|
290
|
-
* ...user,
|
|
291
|
-
* email: user.email.replace('.company.com', '.example.com')
|
|
292
|
-
* }));
|
|
293
|
-
* ```
|
|
294
868
|
*/
|
|
295
869
|
export type ISetMapped<K, KM extends MapSetKeyType> = Iterable<K> &
|
|
296
870
|
Readonly<ISetMappedInterface<K, KM>>;
|
|
297
871
|
|
|
298
|
-
/**
|
|
299
|
-
* Provides utility functions for ISetMapped.
|
|
300
|
-
*/
|
|
872
|
+
/** Provides utility functions for ISetMapped. */
|
|
301
873
|
export namespace ISetMapped {
|
|
302
874
|
/**
|
|
303
|
-
* Creates a new ISetMapped instance with custom element transformation
|
|
875
|
+
* Creates a new ISetMapped instance with custom element transformation
|
|
876
|
+
* functions.
|
|
304
877
|
*
|
|
305
|
-
* This factory function creates an immutable set that can use complex objects
|
|
306
|
-
* by providing bidirectional transformation functions. The
|
|
307
|
-
* your custom element type to a primitive type that
|
|
308
|
-
* `fromKey` reconstructs the original
|
|
878
|
+
* This factory function creates an immutable set that can use complex objects
|
|
879
|
+
* as elements by providing bidirectional transformation functions. The
|
|
880
|
+
* `toKey` function converts your custom element type to a primitive type that
|
|
881
|
+
* can be efficiently stored, while `fromKey` reconstructs the original
|
|
882
|
+
* element type for iteration and access.
|
|
309
883
|
*
|
|
310
884
|
* **Performance:** O(n) where n is the number of elements in the iterable.
|
|
311
885
|
*
|
|
312
|
-
* @template K The type of the custom elements.
|
|
313
|
-
* @template KM The type of the mapped primitive keys.
|
|
314
|
-
* @param iterable An iterable of elements using the custom element type.
|
|
315
|
-
* @param toKey A function that converts a custom element `K` to a primitive key `KM`.
|
|
316
|
-
* This function must be deterministic and produce unique values for unique elements.
|
|
317
|
-
* @param fromKey A function that converts a primitive key `KM` back to the custom element `K`.
|
|
318
|
-
* This should be the inverse of `toKey`.
|
|
319
|
-
* @returns A new ISetMapped instance containing all unique elements from the iterable.
|
|
320
|
-
*
|
|
321
886
|
* @example
|
|
322
|
-
* ```typescript
|
|
323
|
-
* // Example 1: Product catalog with SKU-based identity
|
|
324
|
-
* type Product = { sku: string; name: string; price: number; category: string };
|
|
325
|
-
*
|
|
326
|
-
* const productToKey = (product: Product): string => product.sku;
|
|
327
|
-
* const keyToProduct = (sku: string): Product => {
|
|
328
|
-
* // In practice, this might fetch from a product service or cache
|
|
329
|
-
* return {
|
|
330
|
-
* sku,
|
|
331
|
-
* name: `Product ${sku}`,
|
|
332
|
-
* price: 0,
|
|
333
|
-
* category: "unknown"
|
|
334
|
-
* };
|
|
335
|
-
* };
|
|
336
|
-
*
|
|
337
|
-
* const productSet = ISetMapped.create<Product, string>(
|
|
338
|
-
* [
|
|
339
|
-
* { sku: "LAPTOP-001", name: "Gaming Laptop", price: 1299, category: "electronics" },
|
|
340
|
-
* { sku: "MOUSE-002", name: "Wireless Mouse", price: 49, category: "accessories" },
|
|
341
|
-
* { sku: "LAPTOP-001", name: "Gaming Laptop", price: 1299, category: "electronics" } // Duplicate SKU
|
|
342
|
-
* ],
|
|
343
|
-
* productToKey,
|
|
344
|
-
* keyToProduct
|
|
345
|
-
* );
|
|
346
887
|
*
|
|
347
|
-
*
|
|
348
|
-
*
|
|
888
|
+
* ```ts
|
|
889
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
349
890
|
*
|
|
350
|
-
*
|
|
351
|
-
* type Location = { name: string; lat: number; lng: number; type: string };
|
|
891
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
352
892
|
*
|
|
353
|
-
*
|
|
354
|
-
* const
|
|
355
|
-
* const [latStr, lngStr] = key.split(',');
|
|
356
|
-
* return {
|
|
357
|
-
* name: "Unknown Location",
|
|
358
|
-
* lat: parseFloat(latStr),
|
|
359
|
-
* lng: parseFloat(lngStr),
|
|
360
|
-
* type: "point"
|
|
361
|
-
* };
|
|
362
|
-
* };
|
|
893
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
894
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
363
895
|
*
|
|
364
|
-
* const
|
|
896
|
+
* const set = ISetMapped.create<Point, string>(
|
|
365
897
|
* [
|
|
366
|
-
* {
|
|
367
|
-
* {
|
|
898
|
+
* { x: 1, tag: 'a' },
|
|
899
|
+
* { x: 1, tag: 'a' },
|
|
900
|
+
* { x: 2, tag: 'b' },
|
|
368
901
|
* ],
|
|
369
|
-
*
|
|
370
|
-
*
|
|
371
|
-
* );
|
|
372
|
-
*
|
|
373
|
-
*
|
|
374
|
-
*
|
|
375
|
-
*
|
|
376
|
-
*
|
|
377
|
-
* const keyToUser = (key: string): User => {
|
|
378
|
-
* const [tenant, idStr] = key.split(':');
|
|
379
|
-
* return {
|
|
380
|
-
* id: Number(idStr),
|
|
381
|
-
* tenant,
|
|
382
|
-
* email: `user${idStr}@${tenant}.com`,
|
|
383
|
-
* active: true
|
|
384
|
-
* };
|
|
385
|
-
* };
|
|
386
|
-
*
|
|
387
|
-
* const userSet = ISetMapped.create<User, string>(
|
|
388
|
-
* [],
|
|
389
|
-
* userToKey,
|
|
390
|
-
* keyToUser
|
|
391
|
-
* )
|
|
392
|
-
* .add({ id: 1, tenant: "acme", email: "alice@acme.com", active: true })
|
|
393
|
-
* .add({ id: 2, tenant: "acme", email: "bob@acme.com", active: false });
|
|
394
|
-
*
|
|
395
|
-
* console.log(userSet.size); // Output: 2
|
|
396
|
-
*
|
|
397
|
-
* // Example 4: Empty set with type specification
|
|
398
|
-
* const emptyProductSet = ISetMapped.create<Product, string>(
|
|
399
|
-
* [],
|
|
400
|
-
* productToKey,
|
|
401
|
-
* keyToProduct
|
|
402
|
-
* );
|
|
403
|
-
* console.log(emptyProductSet.isEmpty); // Output: true
|
|
902
|
+
* toKey,
|
|
903
|
+
* fromKey,
|
|
904
|
+
* );
|
|
905
|
+
*
|
|
906
|
+
* assert.deepStrictEqual(Array.from(set), [
|
|
907
|
+
* { x: 1, tag: 'a' },
|
|
908
|
+
* { x: 2, tag: 'b' },
|
|
909
|
+
* ]);
|
|
404
910
|
* ```
|
|
911
|
+
*
|
|
912
|
+
* @template K The type of the custom elements.
|
|
913
|
+
* @template KM The type of the mapped primitive keys.
|
|
914
|
+
* @param iterable An iterable of elements using the custom element type.
|
|
915
|
+
* @param toKey A function that converts a custom element `K` to a primitive
|
|
916
|
+
* key `KM`. This function must be deterministic and produce unique values
|
|
917
|
+
* for unique elements.
|
|
918
|
+
* @param fromKey A function that converts a primitive key `KM` back to the
|
|
919
|
+
* custom element `K`. This should be the inverse of `toKey`.
|
|
920
|
+
* @returns A new ISetMapped instance containing all unique elements from the
|
|
921
|
+
* iterable.
|
|
405
922
|
*/
|
|
406
923
|
export const create = <K, KM extends MapSetKeyType>(
|
|
407
924
|
iterable: Iterable<K>,
|
|
@@ -412,99 +929,56 @@ export namespace ISetMapped {
|
|
|
412
929
|
/**
|
|
413
930
|
* Checks if two ISetMapped instances are structurally equal.
|
|
414
931
|
*
|
|
415
|
-
* Two ISetMapped instances are considered equal if they have the same size
|
|
416
|
-
* exactly the same elements. The comparison is performed on the
|
|
417
|
-
* so the transformation functions themselves don't
|
|
418
|
-
* compared based on their mapped key
|
|
932
|
+
* Two ISetMapped instances are considered equal if they have the same size
|
|
933
|
+
* and contain exactly the same elements. The comparison is performed on the
|
|
934
|
+
* underlying mapped keys, so the transformation functions themselves don't
|
|
935
|
+
* need to be identical. Elements are compared based on their mapped key
|
|
936
|
+
* representations.
|
|
419
937
|
*
|
|
420
938
|
* **Performance:** O(n) where n is the size of the smaller set.
|
|
421
939
|
*
|
|
422
|
-
* @template K The type of the custom elements.
|
|
423
|
-
* @template KM The type of the mapped primitive keys.
|
|
424
|
-
* @param a The first ISetMapped instance to compare.
|
|
425
|
-
* @param b The second ISetMapped instance to compare.
|
|
426
|
-
* @returns `true` if the sets contain exactly the same elements, `false` otherwise.
|
|
427
|
-
*
|
|
428
940
|
* @example
|
|
429
|
-
* ```typescript
|
|
430
|
-
* // Example with coordinate-based elements
|
|
431
|
-
* type Point = { x: number; y: number; label?: string };
|
|
432
|
-
* const pointToKey = (p: Point): string => `${p.x},${p.y}`;
|
|
433
|
-
* const keyToPoint = (s: string): Point => {
|
|
434
|
-
* const [x, y] = s.split(',').map(Number);
|
|
435
|
-
* return { x, y };
|
|
436
|
-
* };
|
|
437
|
-
*
|
|
438
|
-
* const set1 = ISetMapped.create<Point, string>(
|
|
439
|
-
* [{ x: 1, y: 2, label: "A" }, { x: 3, y: 4, label: "B" }],
|
|
440
|
-
* pointToKey,
|
|
441
|
-
* keyToPoint
|
|
442
|
-
* );
|
|
443
|
-
*
|
|
444
|
-
* const set2 = ISetMapped.create<Point, string>(
|
|
445
|
-
* [{ x: 3, y: 4, label: "Different" }, { x: 1, y: 2, label: "Labels" }], // Order doesn't matter
|
|
446
|
-
* pointToKey,
|
|
447
|
-
* keyToPoint
|
|
448
|
-
* );
|
|
449
941
|
*
|
|
450
|
-
*
|
|
451
|
-
*
|
|
452
|
-
* pointToKey,
|
|
453
|
-
* keyToPoint
|
|
454
|
-
* );
|
|
942
|
+
* ```ts
|
|
943
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
455
944
|
*
|
|
456
|
-
*
|
|
457
|
-
* console.log(ISetMapped.equal(set1, set3)); // false (different coordinates)
|
|
945
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
458
946
|
*
|
|
459
|
-
* //
|
|
460
|
-
*
|
|
461
|
-
* const userToKey = (u: User): string => `${u.department}:${u.id}`;
|
|
462
|
-
* const keyToUser = (k: string): User => {
|
|
463
|
-
* const [department, idStr] = k.split(':');
|
|
464
|
-
* return { id: Number(idStr), department, name: "" };
|
|
465
|
-
* };
|
|
947
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
948
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
466
949
|
*
|
|
467
|
-
* const
|
|
950
|
+
* const first = ISetMapped.create<Point, string>(
|
|
468
951
|
* [
|
|
469
|
-
* {
|
|
470
|
-
* {
|
|
952
|
+
* { x: 1, tag: 'a' },
|
|
953
|
+
* { x: 2, tag: 'b' },
|
|
471
954
|
* ],
|
|
472
|
-
*
|
|
473
|
-
*
|
|
955
|
+
* toKey,
|
|
956
|
+
* fromKey,
|
|
474
957
|
* );
|
|
475
|
-
*
|
|
476
|
-
* const users2 = ISetMapped.create<User, string>(
|
|
958
|
+
* const second = ISetMapped.create<Point, string>(
|
|
477
959
|
* [
|
|
478
|
-
* {
|
|
479
|
-
* {
|
|
960
|
+
* { x: 2, tag: 'b' },
|
|
961
|
+
* { x: 1, tag: 'a' },
|
|
480
962
|
* ],
|
|
481
|
-
*
|
|
482
|
-
*
|
|
963
|
+
* toKey,
|
|
964
|
+
* fromKey,
|
|
483
965
|
* );
|
|
484
|
-
*
|
|
485
|
-
*
|
|
486
|
-
*
|
|
487
|
-
*
|
|
488
|
-
* const empty1 = ISetMapped.create<Point, string>([], pointToKey, keyToPoint);
|
|
489
|
-
* const empty2 = ISetMapped.create<Point, string>([], pointToKey, keyToPoint);
|
|
490
|
-
* console.log(ISetMapped.equal(empty1, empty2)); // true
|
|
491
|
-
*
|
|
492
|
-
* // Sets with different transformation functions but same logical content
|
|
493
|
-
* const alternativePointToKey = (p: Point): string => `(${p.x},${p.y})`; // Different format
|
|
494
|
-
* const alternativeKeyToPoint = (s: string): Point => {
|
|
495
|
-
* const match = s.match(/\((\d+),(\d+)\)/)!;
|
|
496
|
-
* return { x: Number(match[1]), y: Number(match[2]) };
|
|
497
|
-
* };
|
|
498
|
-
*
|
|
499
|
-
* const set4 = ISetMapped.create<Point, string>(
|
|
500
|
-
* [{ x: 1, y: 2 }, { x: 3, y: 4 }],
|
|
501
|
-
* alternativePointToKey,
|
|
502
|
-
* alternativeKeyToPoint
|
|
966
|
+
* const third = ISetMapped.create<Point, string>(
|
|
967
|
+
* [{ x: 3, tag: 'c' }],
|
|
968
|
+
* toKey,
|
|
969
|
+
* fromKey,
|
|
503
970
|
* );
|
|
504
971
|
*
|
|
505
|
-
*
|
|
506
|
-
*
|
|
972
|
+
* assert.ok(ISetMapped.equal(first, second));
|
|
973
|
+
* assert.notOk(ISetMapped.equal(first, third));
|
|
507
974
|
* ```
|
|
975
|
+
*
|
|
976
|
+
* @template K The type of the custom elements.
|
|
977
|
+
* @template KM The type of the mapped primitive keys.
|
|
978
|
+
* @param a The first ISetMapped instance to compare.
|
|
979
|
+
* @param b The second ISetMapped instance to compare.
|
|
980
|
+
* @returns `true` if the sets contain exactly the same elements, `false`
|
|
981
|
+
* otherwise.
|
|
508
982
|
*/
|
|
509
983
|
export const equal = <K, KM extends MapSetKeyType>(
|
|
510
984
|
a: ISetMapped<K, KM>,
|
|
@@ -513,36 +987,45 @@ export namespace ISetMapped {
|
|
|
513
987
|
|
|
514
988
|
/**
|
|
515
989
|
* Computes the difference between two ISetMapped instances.
|
|
516
|
-
*
|
|
517
|
-
* @template KM The type of the mapped keys.
|
|
518
|
-
* @param oldSet The original set.
|
|
519
|
-
* @param newSet The new set.
|
|
520
|
-
* @returns An object containing sets of added and deleted elements.
|
|
990
|
+
*
|
|
521
991
|
* @example
|
|
522
|
-
* ```typescript
|
|
523
|
-
* type Tag = { name: string };
|
|
524
|
-
* const tagToKey = (t: Tag): string => t.name;
|
|
525
|
-
* const keyToTag = (name: string): Tag => ({ name });
|
|
526
992
|
*
|
|
527
|
-
*
|
|
528
|
-
*
|
|
529
|
-
*
|
|
530
|
-
*
|
|
993
|
+
* ```ts
|
|
994
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
995
|
+
*
|
|
996
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
997
|
+
*
|
|
998
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
999
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
1000
|
+
*
|
|
1001
|
+
* const previous = ISetMapped.create<Point, string>(
|
|
1002
|
+
* [
|
|
1003
|
+
* { x: 1, tag: 'a' },
|
|
1004
|
+
* { x: 2, tag: 'b' },
|
|
1005
|
+
* ],
|
|
1006
|
+
* toKey,
|
|
1007
|
+
* fromKey,
|
|
531
1008
|
* );
|
|
532
|
-
* const
|
|
533
|
-
* [
|
|
534
|
-
*
|
|
535
|
-
*
|
|
1009
|
+
* const current = ISetMapped.create<Point, string>(
|
|
1010
|
+
* [
|
|
1011
|
+
* { x: 2, tag: 'b' },
|
|
1012
|
+
* { x: 3, tag: 'c' },
|
|
1013
|
+
* ],
|
|
1014
|
+
* toKey,
|
|
1015
|
+
* fromKey,
|
|
536
1016
|
* );
|
|
537
1017
|
*
|
|
538
|
-
* const
|
|
539
|
-
*
|
|
540
|
-
* console.log("Deleted tags:", diffResult.deleted.toArray().map(t => t.name));
|
|
541
|
-
* // Output: Deleted tags: ["typescript"]
|
|
1018
|
+
* const { added, deleted } = ISetMapped.diff(previous, current);
|
|
542
1019
|
*
|
|
543
|
-
*
|
|
544
|
-
*
|
|
1020
|
+
* assert.deepStrictEqual(Array.from(added), [{ x: 3, tag: 'c' }]);
|
|
1021
|
+
* assert.deepStrictEqual(Array.from(deleted), [{ x: 1, tag: 'a' }]);
|
|
545
1022
|
* ```
|
|
1023
|
+
*
|
|
1024
|
+
* @template K The type of the elements.
|
|
1025
|
+
* @template KM The type of the mapped keys.
|
|
1026
|
+
* @param oldSet The original set.
|
|
1027
|
+
* @param newSet The new set.
|
|
1028
|
+
* @returns An object containing sets of added and deleted elements.
|
|
546
1029
|
*/
|
|
547
1030
|
export const diff = <K, KM extends MapSetKeyType>(
|
|
548
1031
|
oldSet: ISetMapped<K, KM>,
|
|
@@ -554,31 +1037,41 @@ export namespace ISetMapped {
|
|
|
554
1037
|
|
|
555
1038
|
/**
|
|
556
1039
|
* Computes the intersection of two ISetMapped instances.
|
|
557
|
-
*
|
|
558
|
-
* @template KM The type of the mapped keys.
|
|
559
|
-
* @param a The first set.
|
|
560
|
-
* @param b The second set.
|
|
561
|
-
* @returns A new ISetMapped instance representing the intersection.
|
|
1040
|
+
*
|
|
562
1041
|
* @example
|
|
563
|
-
* ```typescript
|
|
564
|
-
* type Permission = { id: string };
|
|
565
|
-
* const permToKey = (p: Permission): string => p.id;
|
|
566
|
-
* const keyToPerm = (id: string): Permission => ({ id });
|
|
567
1042
|
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
*
|
|
1043
|
+
* ```ts
|
|
1044
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
1045
|
+
*
|
|
1046
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
1047
|
+
*
|
|
1048
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
1049
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
1050
|
+
*
|
|
1051
|
+
* const left = ISetMapped.create<Point, string>(
|
|
1052
|
+
* [
|
|
1053
|
+
* { x: 1, tag: 'a' },
|
|
1054
|
+
* { x: 2, tag: 'b' },
|
|
1055
|
+
* ],
|
|
1056
|
+
* toKey,
|
|
1057
|
+
* fromKey,
|
|
572
1058
|
* );
|
|
573
|
-
* const
|
|
574
|
-
* [{
|
|
575
|
-
*
|
|
576
|
-
*
|
|
1059
|
+
* const right = ISetMapped.create<Point, string>(
|
|
1060
|
+
* [{ x: 2, tag: 'b' }],
|
|
1061
|
+
* toKey,
|
|
1062
|
+
* fromKey,
|
|
577
1063
|
* );
|
|
578
1064
|
*
|
|
579
|
-
* const
|
|
580
|
-
*
|
|
1065
|
+
* const overlap = ISetMapped.intersection(left, right);
|
|
1066
|
+
*
|
|
1067
|
+
* assert.deepStrictEqual(Array.from(overlap), [{ x: 2, tag: 'b' }]);
|
|
581
1068
|
* ```
|
|
1069
|
+
*
|
|
1070
|
+
* @template K The type of the elements.
|
|
1071
|
+
* @template KM The type of the mapped keys.
|
|
1072
|
+
* @param a The first set.
|
|
1073
|
+
* @param b The second set.
|
|
1074
|
+
* @returns A new ISetMapped instance representing the intersection.
|
|
582
1075
|
*/
|
|
583
1076
|
export const intersection = <K, KM extends MapSetKeyType>(
|
|
584
1077
|
a: ISetMapped<K, KM>,
|
|
@@ -587,33 +1080,41 @@ export namespace ISetMapped {
|
|
|
587
1080
|
|
|
588
1081
|
/**
|
|
589
1082
|
* Computes the union of two ISetMapped instances.
|
|
1083
|
+
*
|
|
1084
|
+
* @example
|
|
1085
|
+
*
|
|
1086
|
+
* ```ts
|
|
1087
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
1088
|
+
*
|
|
1089
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
1090
|
+
*
|
|
1091
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
1092
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
1093
|
+
*
|
|
1094
|
+
* const left = ISetMapped.create<Point, string>(
|
|
1095
|
+
* [{ x: 1, tag: 'a' }],
|
|
1096
|
+
* toKey,
|
|
1097
|
+
* fromKey,
|
|
1098
|
+
* );
|
|
1099
|
+
* const right = ISetMapped.create<Point, string>(
|
|
1100
|
+
* [{ x: 2, tag: 'b' }],
|
|
1101
|
+
* toKey,
|
|
1102
|
+
* fromKey,
|
|
1103
|
+
* );
|
|
1104
|
+
*
|
|
1105
|
+
* const combined = ISetMapped.union(left, right);
|
|
1106
|
+
*
|
|
1107
|
+
* assert.deepStrictEqual(Array.from(combined), [
|
|
1108
|
+
* { x: 1, tag: 'a' },
|
|
1109
|
+
* { x: 2, tag: 'b' },
|
|
1110
|
+
* ]);
|
|
1111
|
+
* ```
|
|
1112
|
+
*
|
|
590
1113
|
* @template K The type of the elements.
|
|
591
1114
|
* @template KM The type of the mapped keys.
|
|
592
1115
|
* @param a The first set.
|
|
593
1116
|
* @param b The second set.
|
|
594
1117
|
* @returns A new ISetMapped instance representing the union.
|
|
595
|
-
* @example
|
|
596
|
-
* ```typescript
|
|
597
|
-
* type FeatureFlag = { flagName: string };
|
|
598
|
-
* const flagToKey = (f: FeatureFlag): string => f.flagName;
|
|
599
|
-
* const keyToFlag = (name: string): FeatureFlag => ({ flagName: name });
|
|
600
|
-
*
|
|
601
|
-
* const setA = ISetMapped.create<FeatureFlag, string>(
|
|
602
|
-
* [{ flagName: "newUI" }, { flagName: "betaFeature" }],
|
|
603
|
-
* flagToKey,
|
|
604
|
-
* keyToFlag
|
|
605
|
-
* );
|
|
606
|
-
* const setB = ISetMapped.create<FeatureFlag, string>(
|
|
607
|
-
* [{ flagName: "betaFeature" }, { flagName: "darkMode" }],
|
|
608
|
-
* flagToKey,
|
|
609
|
-
* keyToFlag
|
|
610
|
-
* );
|
|
611
|
-
*
|
|
612
|
-
* const combinedFlags = ISetMapped.union(setA, setB);
|
|
613
|
-
* // The order might vary as sets are unordered internally.
|
|
614
|
-
* console.log(combinedFlags.toArray().map(f => f.flagName).toSorted());
|
|
615
|
-
* // Output: ["betaFeature", "darkMode", "newUI"]
|
|
616
|
-
* ```
|
|
617
1118
|
*/
|
|
618
1119
|
export const union = <K, KM extends MapSetKeyType>(
|
|
619
1120
|
a: ISetMapped<K, KM>,
|
|
@@ -622,13 +1123,17 @@ export namespace ISetMapped {
|
|
|
622
1123
|
}
|
|
623
1124
|
|
|
624
1125
|
/**
|
|
625
|
-
* Internal class implementation for ISetMapped providing immutable set
|
|
1126
|
+
* Internal class implementation for ISetMapped providing immutable set
|
|
1127
|
+
* operations with element transformation.
|
|
626
1128
|
*
|
|
627
|
-
* This class implements the ISetMapped interface by maintaining a JavaScript
|
|
628
|
-
* internally while exposing an API that works with
|
|
629
|
-
* custom
|
|
1129
|
+
* This class implements the ISetMapped interface by maintaining a JavaScript
|
|
1130
|
+
* Set with primitive keys internally while exposing an API that works with
|
|
1131
|
+
* custom element types. The transformation between custom and primitive
|
|
1132
|
+
* elements is handled transparently through the provided `toKey` and `fromKey`
|
|
1133
|
+
* functions.
|
|
630
1134
|
*
|
|
631
1135
|
* **Implementation Details:**
|
|
1136
|
+
*
|
|
632
1137
|
* - Uses ReadonlySet<KM> internally where KM is the primitive key type
|
|
633
1138
|
* - Stores transformation functions for bidirectional element conversion
|
|
634
1139
|
* - Implements copy-on-write semantics for efficiency
|
|
@@ -652,13 +1157,13 @@ class ISetMappedClass<K, KM extends MapSetKeyType>
|
|
|
652
1157
|
* Constructs an ISetMappedClass instance with custom element transformation.
|
|
653
1158
|
*
|
|
654
1159
|
* @param iterable An iterable of elements using the custom element type K.
|
|
655
|
-
* @param toKey A function that converts a custom element K to a primitive key
|
|
656
|
-
*
|
|
657
|
-
* @param fromKey A function that converts a primitive key KM back to the
|
|
658
|
-
*
|
|
1160
|
+
* @param toKey A function that converts a custom element K to a primitive key
|
|
1161
|
+
* KM. Must be deterministic and produce unique values for unique elements.
|
|
1162
|
+
* @param fromKey A function that converts a primitive key KM back to the
|
|
1163
|
+
* custom element K. Should be the inverse of the toKey function.
|
|
659
1164
|
* @param showNotFoundMessage Whether to log warning messages when operations
|
|
660
|
-
*
|
|
661
|
-
*
|
|
1165
|
+
* are performed on non-existent elements. Useful for debugging. Defaults to
|
|
1166
|
+
* false for production use.
|
|
662
1167
|
* @internal Use ISetMapped.create() instead of calling this constructor directly.
|
|
663
1168
|
*/
|
|
664
1169
|
constructor(
|
|
@@ -692,8 +1197,10 @@ class ISetMappedClass<K, KM extends MapSetKeyType>
|
|
|
692
1197
|
every<L extends K>(
|
|
693
1198
|
predicate: (key: K) => key is L,
|
|
694
1199
|
): this is ISetMapped<L, KM>;
|
|
1200
|
+
|
|
695
1201
|
/** @inheritdoc */
|
|
696
1202
|
every(predicate: (key: K) => boolean): boolean;
|
|
1203
|
+
|
|
697
1204
|
/** @inheritdoc */
|
|
698
1205
|
every(predicate: (key: K) => boolean): boolean {
|
|
699
1206
|
for (const key of this.values()) {
|
|
@@ -845,6 +1352,33 @@ class ISetMappedClass<K, KM extends MapSetKeyType>
|
|
|
845
1352
|
}
|
|
846
1353
|
|
|
847
1354
|
/**
|
|
1355
|
+
* @example
|
|
1356
|
+
*
|
|
1357
|
+
* ```ts
|
|
1358
|
+
* type Point = Readonly<{ x: number; tag: string }>;
|
|
1359
|
+
*
|
|
1360
|
+
* const toKey = (point: Point) => JSON.stringify(point);
|
|
1361
|
+
*
|
|
1362
|
+
* // eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
1363
|
+
* const fromKey = (key: string) => JSON.parse(key) as Point;
|
|
1364
|
+
*
|
|
1365
|
+
* const set = ISetMapped.create<Point, string>(
|
|
1366
|
+
* [
|
|
1367
|
+
* { x: 1, tag: 'a' },
|
|
1368
|
+
* { x: 2, tag: 'b' },
|
|
1369
|
+
* ],
|
|
1370
|
+
* toKey,
|
|
1371
|
+
* fromKey,
|
|
1372
|
+
* );
|
|
1373
|
+
*
|
|
1374
|
+
* const collected = Array.from(set);
|
|
1375
|
+
*
|
|
1376
|
+
* assert.deepStrictEqual(collected, [
|
|
1377
|
+
* { x: 1, tag: 'a' },
|
|
1378
|
+
* { x: 2, tag: 'b' },
|
|
1379
|
+
* ]);
|
|
1380
|
+
* ```
|
|
1381
|
+
*
|
|
848
1382
|
* @inheritdoc
|
|
849
1383
|
*/
|
|
850
1384
|
*[Symbol.iterator](): Iterator<K> {
|