ts-data-forge 1.0.0
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/LICENSE +201 -0
- package/README.md +534 -0
- package/package.json +101 -0
- package/src/array/array-utils-creation.test.mts +443 -0
- package/src/array/array-utils-modification.test.mts +197 -0
- package/src/array/array-utils-overload-type-error.test.mts +149 -0
- package/src/array/array-utils-reducing-value.test.mts +425 -0
- package/src/array/array-utils-search.test.mts +169 -0
- package/src/array/array-utils-set-op.test.mts +335 -0
- package/src/array/array-utils-slice-clamped.test.mts +113 -0
- package/src/array/array-utils-slicing.test.mts +316 -0
- package/src/array/array-utils-transformation.test.mts +790 -0
- package/src/array/array-utils-validation.test.mts +492 -0
- package/src/array/array-utils.mts +4000 -0
- package/src/array/array.test.mts +146 -0
- package/src/array/index.mts +2 -0
- package/src/array/tuple-utils.mts +519 -0
- package/src/array/tuple-utils.test.mts +518 -0
- package/src/collections/imap-mapped.mts +801 -0
- package/src/collections/imap-mapped.test.mts +860 -0
- package/src/collections/imap.mts +651 -0
- package/src/collections/imap.test.mts +932 -0
- package/src/collections/index.mts +6 -0
- package/src/collections/iset-mapped.mts +889 -0
- package/src/collections/iset-mapped.test.mts +1187 -0
- package/src/collections/iset.mts +682 -0
- package/src/collections/iset.test.mts +1084 -0
- package/src/collections/queue.mts +390 -0
- package/src/collections/queue.test.mts +282 -0
- package/src/collections/stack.mts +423 -0
- package/src/collections/stack.test.mts +225 -0
- package/src/expect-type.mts +206 -0
- package/src/functional/index.mts +4 -0
- package/src/functional/match.mts +300 -0
- package/src/functional/match.test.mts +177 -0
- package/src/functional/optional.mts +733 -0
- package/src/functional/optional.test.mts +619 -0
- package/src/functional/pipe.mts +212 -0
- package/src/functional/pipe.test.mts +85 -0
- package/src/functional/result.mts +1134 -0
- package/src/functional/result.test.mts +777 -0
- package/src/globals.d.mts +38 -0
- package/src/guard/has-key.mts +119 -0
- package/src/guard/has-key.test.mts +219 -0
- package/src/guard/index.mts +7 -0
- package/src/guard/is-non-empty-string.mts +108 -0
- package/src/guard/is-non-empty-string.test.mts +91 -0
- package/src/guard/is-non-null-object.mts +106 -0
- package/src/guard/is-non-null-object.test.mts +90 -0
- package/src/guard/is-primitive.mts +165 -0
- package/src/guard/is-primitive.test.mts +102 -0
- package/src/guard/is-record.mts +153 -0
- package/src/guard/is-record.test.mts +112 -0
- package/src/guard/is-type.mts +450 -0
- package/src/guard/is-type.test.mts +496 -0
- package/src/guard/key-is-in.mts +163 -0
- package/src/guard/key-is-in.test.mts +19 -0
- package/src/index.mts +10 -0
- package/src/iterator/index.mts +1 -0
- package/src/iterator/range.mts +120 -0
- package/src/iterator/range.test.mts +33 -0
- package/src/json/index.mts +1 -0
- package/src/json/json.mts +711 -0
- package/src/json/json.test.mts +628 -0
- package/src/number/branded-types/finite-number.mts +354 -0
- package/src/number/branded-types/finite-number.test.mts +135 -0
- package/src/number/branded-types/index.mts +26 -0
- package/src/number/branded-types/int.mts +278 -0
- package/src/number/branded-types/int.test.mts +140 -0
- package/src/number/branded-types/int16.mts +192 -0
- package/src/number/branded-types/int16.test.mts +170 -0
- package/src/number/branded-types/int32.mts +193 -0
- package/src/number/branded-types/int32.test.mts +170 -0
- package/src/number/branded-types/non-negative-finite-number.mts +223 -0
- package/src/number/branded-types/non-negative-finite-number.test.mts +188 -0
- package/src/number/branded-types/non-negative-int16.mts +187 -0
- package/src/number/branded-types/non-negative-int16.test.mts +201 -0
- package/src/number/branded-types/non-negative-int32.mts +187 -0
- package/src/number/branded-types/non-negative-int32.test.mts +204 -0
- package/src/number/branded-types/non-zero-finite-number.mts +229 -0
- package/src/number/branded-types/non-zero-finite-number.test.mts +198 -0
- package/src/number/branded-types/non-zero-int.mts +167 -0
- package/src/number/branded-types/non-zero-int.test.mts +177 -0
- package/src/number/branded-types/non-zero-int16.mts +196 -0
- package/src/number/branded-types/non-zero-int16.test.mts +195 -0
- package/src/number/branded-types/non-zero-int32.mts +196 -0
- package/src/number/branded-types/non-zero-int32.test.mts +197 -0
- package/src/number/branded-types/non-zero-safe-int.mts +196 -0
- package/src/number/branded-types/non-zero-safe-int.test.mts +232 -0
- package/src/number/branded-types/non-zero-uint16.mts +189 -0
- package/src/number/branded-types/non-zero-uint16.test.mts +199 -0
- package/src/number/branded-types/non-zero-uint32.mts +189 -0
- package/src/number/branded-types/non-zero-uint32.test.mts +199 -0
- package/src/number/branded-types/positive-finite-number.mts +241 -0
- package/src/number/branded-types/positive-finite-number.test.mts +204 -0
- package/src/number/branded-types/positive-int.mts +304 -0
- package/src/number/branded-types/positive-int.test.mts +176 -0
- package/src/number/branded-types/positive-int16.mts +188 -0
- package/src/number/branded-types/positive-int16.test.mts +197 -0
- package/src/number/branded-types/positive-int32.mts +188 -0
- package/src/number/branded-types/positive-int32.test.mts +197 -0
- package/src/number/branded-types/positive-safe-int.mts +187 -0
- package/src/number/branded-types/positive-safe-int.test.mts +210 -0
- package/src/number/branded-types/positive-uint16.mts +188 -0
- package/src/number/branded-types/positive-uint16.test.mts +203 -0
- package/src/number/branded-types/positive-uint32.mts +188 -0
- package/src/number/branded-types/positive-uint32.test.mts +203 -0
- package/src/number/branded-types/safe-int.mts +291 -0
- package/src/number/branded-types/safe-int.test.mts +170 -0
- package/src/number/branded-types/safe-uint.mts +187 -0
- package/src/number/branded-types/safe-uint.test.mts +176 -0
- package/src/number/branded-types/uint.mts +179 -0
- package/src/number/branded-types/uint.test.mts +158 -0
- package/src/number/branded-types/uint16.mts +186 -0
- package/src/number/branded-types/uint16.test.mts +170 -0
- package/src/number/branded-types/uint32.mts +218 -0
- package/src/number/branded-types/uint32.test.mts +170 -0
- package/src/number/enum/index.mts +2 -0
- package/src/number/enum/int8.mts +344 -0
- package/src/number/enum/int8.test.mts +180 -0
- package/src/number/enum/uint8.mts +293 -0
- package/src/number/enum/uint8.test.mts +164 -0
- package/src/number/index.mts +4 -0
- package/src/number/num.mts +604 -0
- package/src/number/num.test.mts +242 -0
- package/src/number/refined-number-utils.mts +566 -0
- package/src/object/index.mts +1 -0
- package/src/object/object.mts +447 -0
- package/src/object/object.test.mts +124 -0
- package/src/others/cast-mutable.mts +113 -0
- package/src/others/cast-readonly.mts +192 -0
- package/src/others/cast-readonly.test.mts +89 -0
- package/src/others/if-then.mts +98 -0
- package/src/others/if-then.test.mts +75 -0
- package/src/others/index.mts +7 -0
- package/src/others/map-nullable.mts +172 -0
- package/src/others/map-nullable.test.mts +297 -0
- package/src/others/memoize-function.mts +196 -0
- package/src/others/memoize-function.test.mts +168 -0
- package/src/others/tuple.mts +160 -0
- package/src/others/tuple.test.mts +11 -0
- package/src/others/unknown-to-string.mts +215 -0
- package/src/others/unknown-to-string.test.mts +114 -0
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import { expectType } from '../../expect-type.mjs';
|
|
2
|
+
import { TsVerifiedInternals } from '../refined-number-utils.mjs';
|
|
3
|
+
|
|
4
|
+
type ElementType = FiniteNumber;
|
|
5
|
+
|
|
6
|
+
const typeNameInMessage = 'a finite number';
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
abs,
|
|
10
|
+
min: min_,
|
|
11
|
+
max: max_,
|
|
12
|
+
pow,
|
|
13
|
+
add,
|
|
14
|
+
sub,
|
|
15
|
+
mul,
|
|
16
|
+
div,
|
|
17
|
+
random,
|
|
18
|
+
is,
|
|
19
|
+
castType,
|
|
20
|
+
} = TsVerifiedInternals.RefinedNumberUtils.operatorsForFloat<
|
|
21
|
+
ElementType,
|
|
22
|
+
undefined,
|
|
23
|
+
undefined
|
|
24
|
+
>({
|
|
25
|
+
MIN_VALUE: undefined,
|
|
26
|
+
MAX_VALUE: undefined,
|
|
27
|
+
typeNameInMessage,
|
|
28
|
+
} as const);
|
|
29
|
+
|
|
30
|
+
const floor = (
|
|
31
|
+
x: ElementType,
|
|
32
|
+
): TsVerifiedInternals.RefinedNumberUtils.ToInt<ElementType> =>
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
34
|
+
Math.floor(x) as TsVerifiedInternals.RefinedNumberUtils.ToInt<ElementType>;
|
|
35
|
+
|
|
36
|
+
const ceil = (
|
|
37
|
+
x: ElementType,
|
|
38
|
+
): TsVerifiedInternals.RefinedNumberUtils.ToInt<ElementType> =>
|
|
39
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
40
|
+
Math.ceil(x) as TsVerifiedInternals.RefinedNumberUtils.ToInt<ElementType>;
|
|
41
|
+
|
|
42
|
+
const round = (
|
|
43
|
+
x: ElementType,
|
|
44
|
+
): TsVerifiedInternals.RefinedNumberUtils.ToInt<ElementType> =>
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
|
46
|
+
Math.round(x) as TsVerifiedInternals.RefinedNumberUtils.ToInt<ElementType>;
|
|
47
|
+
|
|
48
|
+
expectType<TsVerifiedInternals.RefinedNumberUtils.ToInt<ElementType>, Int>('=');
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Type guard that checks if a value is a finite number.
|
|
52
|
+
*
|
|
53
|
+
* Returns `true` if the value is a finite number (not NaN, Infinity, or -Infinity).
|
|
54
|
+
* This is stricter than the standard number type, which includes these special values.
|
|
55
|
+
*
|
|
56
|
+
* @param value - The value to check
|
|
57
|
+
* @returns `true` if the value is finite, `false` otherwise
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* isFiniteNumber(42); // true
|
|
62
|
+
* isFiniteNumber(3.14); // true
|
|
63
|
+
* isFiniteNumber(-0); // true
|
|
64
|
+
* isFiniteNumber(Infinity); // false
|
|
65
|
+
* isFiniteNumber(-Infinity); // false
|
|
66
|
+
* isFiniteNumber(NaN); // false
|
|
67
|
+
* isFiniteNumber(1/0); // false (Infinity)
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export const isFiniteNumber = is;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Casts a number to a FiniteNumber branded type.
|
|
74
|
+
*
|
|
75
|
+
* This function validates that the input is finite (not NaN, Infinity, or -Infinity)
|
|
76
|
+
* and returns it with the FiniteNumber brand. This ensures type safety for operations
|
|
77
|
+
* that require finite numeric values.
|
|
78
|
+
*
|
|
79
|
+
* @param value - The value to cast
|
|
80
|
+
* @returns The value as a FiniteNumber branded type
|
|
81
|
+
* @throws {TypeError} If the value is NaN, Infinity, or -Infinity
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* ```typescript
|
|
85
|
+
* const x = asFiniteNumber(5.5); // FiniteNumber
|
|
86
|
+
* const y = asFiniteNumber(-10); // FiniteNumber
|
|
87
|
+
* const z = asFiniteNumber(0); // FiniteNumber
|
|
88
|
+
*
|
|
89
|
+
* // These throw TypeError:
|
|
90
|
+
* // asFiniteNumber(Infinity); // Not finite
|
|
91
|
+
* // asFiniteNumber(-Infinity); // Not finite
|
|
92
|
+
* // asFiniteNumber(NaN); // Not a number
|
|
93
|
+
* // asFiniteNumber(Math.sqrt(-1)); // Results in NaN
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export const asFiniteNumber = castType;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Namespace providing type-safe operations for FiniteNumber branded types.
|
|
100
|
+
*
|
|
101
|
+
* The FiniteNumber type represents any finite numeric value, excluding the
|
|
102
|
+
* special values NaN, Infinity, and -Infinity. All operations are guaranteed
|
|
103
|
+
* to maintain the finite constraint when given finite inputs.
|
|
104
|
+
*
|
|
105
|
+
* This type is essential for:
|
|
106
|
+
* - Mathematical operations that require real numbers
|
|
107
|
+
* - Preventing NaN/Infinity propagation in calculations
|
|
108
|
+
* - Ensuring numeric stability in algorithms
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* // Type validation
|
|
113
|
+
* FiniteNumber.is(3.14); // true
|
|
114
|
+
* FiniteNumber.is(Infinity); // false
|
|
115
|
+
* FiniteNumber.is(0/0); // false (NaN)
|
|
116
|
+
*
|
|
117
|
+
* // Arithmetic with guaranteed finite results
|
|
118
|
+
* const a = asFiniteNumber(10.5);
|
|
119
|
+
* const b = asFiniteNumber(3.2);
|
|
120
|
+
*
|
|
121
|
+
* const sum = FiniteNumber.add(a, b); // FiniteNumber (13.7)
|
|
122
|
+
* const diff = FiniteNumber.sub(a, b); // FiniteNumber (7.3)
|
|
123
|
+
* const product = FiniteNumber.mul(a, b); // FiniteNumber (33.6)
|
|
124
|
+
* const quotient = FiniteNumber.div(a, b); // FiniteNumber (3.28125)
|
|
125
|
+
* const power = FiniteNumber.pow(a, asFiniteNumber(2)); // FiniteNumber (110.25)
|
|
126
|
+
*
|
|
127
|
+
* // Rounding to integers
|
|
128
|
+
* const value = asFiniteNumber(5.7);
|
|
129
|
+
* const floored = FiniteNumber.floor(value); // Int (5)
|
|
130
|
+
* const ceiled = FiniteNumber.ceil(value); // Int (6)
|
|
131
|
+
* const rounded = FiniteNumber.round(value); // Int (6)
|
|
132
|
+
*
|
|
133
|
+
* // Utility operations
|
|
134
|
+
* const absolute = FiniteNumber.abs(asFiniteNumber(-42.5)); // FiniteNumber (42.5)
|
|
135
|
+
* const minimum = FiniteNumber.min(a, b, asFiniteNumber(5)); // FiniteNumber (3.2)
|
|
136
|
+
* const maximum = FiniteNumber.max(a, b, asFiniteNumber(5)); // FiniteNumber (10.5)
|
|
137
|
+
*
|
|
138
|
+
* // Random generation
|
|
139
|
+
* const rand = FiniteNumber.random(asFiniteNumber(0), asFiniteNumber(1)); // Random in [0, 1]
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
export const FiniteNumber = {
|
|
143
|
+
/**
|
|
144
|
+
* Type guard that checks if a value is a finite number.
|
|
145
|
+
*
|
|
146
|
+
* @param value - The value to check
|
|
147
|
+
* @returns `true` if the value is finite, `false` otherwise
|
|
148
|
+
*
|
|
149
|
+
* @see {@link isFiniteNumber} for usage examples
|
|
150
|
+
*/
|
|
151
|
+
is,
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Returns the absolute value of a finite number.
|
|
155
|
+
* @param x - The finite number to get the absolute value of
|
|
156
|
+
* @returns The absolute value as a FiniteNumber
|
|
157
|
+
* @example
|
|
158
|
+
* ```typescript
|
|
159
|
+
* FiniteNumber.abs(asFiniteNumber(-5.5)); // FiniteNumber (5.5)
|
|
160
|
+
* FiniteNumber.abs(asFiniteNumber(3.2)); // FiniteNumber (3.2)
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
abs,
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Returns the minimum value from a list of finite numbers.
|
|
167
|
+
*
|
|
168
|
+
* @param values - The finite numbers to compare (at least one required)
|
|
169
|
+
* @returns The smallest value as a FiniteNumber
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* ```typescript
|
|
173
|
+
* const a = asFiniteNumber(5.5);
|
|
174
|
+
* const b = asFiniteNumber(3.2);
|
|
175
|
+
* const c = asFiniteNumber(7.8);
|
|
176
|
+
*
|
|
177
|
+
* FiniteNumber.min(a, b); // FiniteNumber (3.2)
|
|
178
|
+
* FiniteNumber.min(a, b, c); // FiniteNumber (3.2)
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
min: min_,
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Returns the maximum value from a list of finite numbers.
|
|
185
|
+
*
|
|
186
|
+
* @param values - The finite numbers to compare (at least one required)
|
|
187
|
+
* @returns The largest value as a FiniteNumber
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```typescript
|
|
191
|
+
* const a = asFiniteNumber(5.5);
|
|
192
|
+
* const b = asFiniteNumber(3.2);
|
|
193
|
+
* const c = asFiniteNumber(7.8);
|
|
194
|
+
*
|
|
195
|
+
* FiniteNumber.max(a, b); // FiniteNumber (7.8)
|
|
196
|
+
* FiniteNumber.max(a, b, c); // FiniteNumber (7.8)
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
max: max_,
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Returns the largest integer less than or equal to the given finite number.
|
|
203
|
+
* @param x - The finite number to floor
|
|
204
|
+
* @returns The floor value as an Int
|
|
205
|
+
* @example
|
|
206
|
+
* ```typescript
|
|
207
|
+
* FiniteNumber.floor(asFiniteNumber(5.8)); // Int (5)
|
|
208
|
+
* FiniteNumber.floor(asFiniteNumber(-5.2)); // Int (-6)
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
floor,
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Returns the smallest integer greater than or equal to the given finite number.
|
|
215
|
+
* @param x - The finite number to ceil
|
|
216
|
+
* @returns The ceiling value as an Int
|
|
217
|
+
* @example
|
|
218
|
+
* ```typescript
|
|
219
|
+
* FiniteNumber.ceil(asFiniteNumber(5.2)); // Int (6)
|
|
220
|
+
* FiniteNumber.ceil(asFiniteNumber(-5.8)); // Int (-5)
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
ceil,
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Rounds a finite number to the nearest integer.
|
|
227
|
+
* @param x - The finite number to round
|
|
228
|
+
* @returns The rounded value as an Int
|
|
229
|
+
* @example
|
|
230
|
+
* ```typescript
|
|
231
|
+
* FiniteNumber.round(asFiniteNumber(5.4)); // Int (5)
|
|
232
|
+
* FiniteNumber.round(asFiniteNumber(5.6)); // Int (6)
|
|
233
|
+
* FiniteNumber.round(asFiniteNumber(5.5)); // Int (6)
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
round,
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Generates a random finite number within the specified range.
|
|
240
|
+
*
|
|
241
|
+
* The generated value is uniformly distributed in the range [min, max].
|
|
242
|
+
* Both bounds are inclusive.
|
|
243
|
+
*
|
|
244
|
+
* @param min - The minimum value (inclusive)
|
|
245
|
+
* @param max - The maximum value (inclusive)
|
|
246
|
+
* @returns A random FiniteNumber in the range [min, max]
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```typescript
|
|
250
|
+
* // Random percentage (0-100)
|
|
251
|
+
* const pct = FiniteNumber.random(
|
|
252
|
+
* asFiniteNumber(0),
|
|
253
|
+
* asFiniteNumber(100)
|
|
254
|
+
* );
|
|
255
|
+
*
|
|
256
|
+
* // Random coordinate (-1 to 1)
|
|
257
|
+
* const coord = FiniteNumber.random(
|
|
258
|
+
* asFiniteNumber(-1),
|
|
259
|
+
* asFiniteNumber(1)
|
|
260
|
+
* );
|
|
261
|
+
* ```
|
|
262
|
+
*/
|
|
263
|
+
random,
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Raises a finite number to a power.
|
|
267
|
+
* @param a - The base finite number
|
|
268
|
+
* @param b - The exponent finite number
|
|
269
|
+
* @returns `a ** b` as a FiniteNumber
|
|
270
|
+
* @example
|
|
271
|
+
* ```typescript
|
|
272
|
+
* FiniteNumber.pow(asFiniteNumber(2.5), asFiniteNumber(3)); // FiniteNumber (15.625)
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
pow,
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Adds two finite numbers.
|
|
279
|
+
* @param a - First finite number
|
|
280
|
+
* @param b - Second finite number
|
|
281
|
+
* @returns `a + b` as a FiniteNumber
|
|
282
|
+
* @example
|
|
283
|
+
* ```typescript
|
|
284
|
+
* FiniteNumber.add(asFiniteNumber(5.5), asFiniteNumber(3.2)); // FiniteNumber (8.7)
|
|
285
|
+
* ```
|
|
286
|
+
*/
|
|
287
|
+
add,
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Subtracts two finite numbers.
|
|
291
|
+
* @param a - First finite number
|
|
292
|
+
* @param b - Second finite number
|
|
293
|
+
* @returns `a - b` as a FiniteNumber
|
|
294
|
+
* @example
|
|
295
|
+
* ```typescript
|
|
296
|
+
* FiniteNumber.sub(asFiniteNumber(8.7), asFiniteNumber(3.2)); // FiniteNumber (5.5)
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
299
|
+
sub,
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Multiplies two finite numbers.
|
|
303
|
+
* @param a - First finite number
|
|
304
|
+
* @param b - Second finite number
|
|
305
|
+
* @returns `a * b` as a FiniteNumber
|
|
306
|
+
* @example
|
|
307
|
+
* ```typescript
|
|
308
|
+
* FiniteNumber.mul(asFiniteNumber(5.5), asFiniteNumber(2)); // FiniteNumber (11)
|
|
309
|
+
* ```
|
|
310
|
+
*/
|
|
311
|
+
mul,
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Divides two finite numbers.
|
|
315
|
+
*
|
|
316
|
+
* The divisor must be non-zero (enforced by type constraints).
|
|
317
|
+
* The result is guaranteed to be finite when both inputs are finite
|
|
318
|
+
* and the divisor is non-zero.
|
|
319
|
+
*
|
|
320
|
+
* @param a - The dividend
|
|
321
|
+
* @param b - The divisor (must be non-zero)
|
|
322
|
+
* @returns The quotient `a / b` as a FiniteNumber
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* ```typescript
|
|
326
|
+
* const a = asFiniteNumber(11);
|
|
327
|
+
* const b = asFiniteNumber(2);
|
|
328
|
+
*
|
|
329
|
+
* FiniteNumber.div(a, b); // FiniteNumber (5.5)
|
|
330
|
+
*
|
|
331
|
+
* // With non-zero type guard
|
|
332
|
+
* const divisor = asFiniteNumber(userInput);
|
|
333
|
+
* if (Num.isNonZero(divisor)) {
|
|
334
|
+
* const result = FiniteNumber.div(a, divisor);
|
|
335
|
+
* }
|
|
336
|
+
* ```
|
|
337
|
+
*/
|
|
338
|
+
div,
|
|
339
|
+
} as const;
|
|
340
|
+
|
|
341
|
+
expectType<
|
|
342
|
+
TsVerifiedInternals.RefinedNumberUtils.ToNonNegative<ElementType>,
|
|
343
|
+
NonNegativeFiniteNumber
|
|
344
|
+
>('=');
|
|
345
|
+
|
|
346
|
+
expectType<
|
|
347
|
+
keyof typeof FiniteNumber,
|
|
348
|
+
keyof TsVerifiedInternals.RefinedNumberUtils.NumberClass<ElementType, never>
|
|
349
|
+
>('=');
|
|
350
|
+
|
|
351
|
+
expectType<
|
|
352
|
+
typeof FiniteNumber,
|
|
353
|
+
TsVerifiedInternals.RefinedNumberUtils.NumberClass<ElementType, never>
|
|
354
|
+
>('<=');
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { expectType } from '../../expect-type.mjs';
|
|
2
|
+
import { asFiniteNumber, FiniteNumber } from './finite-number.mjs';
|
|
3
|
+
import { asNonZeroFiniteNumber } from './non-zero-finite-number.mjs';
|
|
4
|
+
|
|
5
|
+
describe('FiniteNumber', () => {
|
|
6
|
+
describe('asFiniteNumber', () => {
|
|
7
|
+
test('accepts valid finite numbers', () => {
|
|
8
|
+
expect(() => asFiniteNumber(0)).not.toThrow();
|
|
9
|
+
expect(() => asFiniteNumber(1)).not.toThrow();
|
|
10
|
+
expect(() => asFiniteNumber(-1)).not.toThrow();
|
|
11
|
+
expect(() => asFiniteNumber(3.14)).not.toThrow();
|
|
12
|
+
expect(() => asFiniteNumber(-2.5)).not.toThrow();
|
|
13
|
+
expect(() => asFiniteNumber(Number.MAX_VALUE)).not.toThrow();
|
|
14
|
+
expect(() => asFiniteNumber(-Number.MAX_VALUE)).not.toThrow();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('rejects non-finite numbers', () => {
|
|
18
|
+
expect(() => asFiniteNumber(Number.NaN)).toThrow(TypeError);
|
|
19
|
+
expect(() => asFiniteNumber(Number.POSITIVE_INFINITY)).toThrow(TypeError);
|
|
20
|
+
expect(() => asFiniteNumber(Number.NEGATIVE_INFINITY)).toThrow(TypeError);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('returns the same value for valid inputs', () => {
|
|
24
|
+
expect(asFiniteNumber(5.5)).toBe(5.5);
|
|
25
|
+
expect(asFiniteNumber(-10)).toBe(-10);
|
|
26
|
+
expect(asFiniteNumber(0)).toBe(0);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test.each([
|
|
30
|
+
{ name: 'Number.NaN', value: Number.NaN },
|
|
31
|
+
{ name: 'Number.POSITIVE_INFINITY', value: Number.POSITIVE_INFINITY },
|
|
32
|
+
{ name: 'Number.NEGATIVE_INFINITY', value: Number.NEGATIVE_INFINITY },
|
|
33
|
+
] as const)(
|
|
34
|
+
`asFiniteNumber($name) should throw a TypeError`,
|
|
35
|
+
({ value }) => {
|
|
36
|
+
expect(() => asFiniteNumber(value)).toThrow(
|
|
37
|
+
new TypeError(`Expected a finite number, got: ${value}`),
|
|
38
|
+
);
|
|
39
|
+
},
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('FiniteNumber.is', () => {
|
|
44
|
+
test('correctly identifies finite numbers', () => {
|
|
45
|
+
expect(FiniteNumber.is(0)).toBe(true);
|
|
46
|
+
expect(FiniteNumber.is(1)).toBe(true);
|
|
47
|
+
expect(FiniteNumber.is(-1)).toBe(true);
|
|
48
|
+
expect(FiniteNumber.is(3.14)).toBe(true);
|
|
49
|
+
expect(FiniteNumber.is(-2.5)).toBe(true);
|
|
50
|
+
expect(FiniteNumber.is(Number.MAX_VALUE)).toBe(true);
|
|
51
|
+
expect(FiniteNumber.is(-Number.MAX_VALUE)).toBe(true);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('correctly identifies non-finite numbers', () => {
|
|
55
|
+
expect(FiniteNumber.is(Number.NaN)).toBe(false);
|
|
56
|
+
expect(FiniteNumber.is(Number.POSITIVE_INFINITY)).toBe(false);
|
|
57
|
+
expect(FiniteNumber.is(Number.NEGATIVE_INFINITY)).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe('mathematical operations', () => {
|
|
62
|
+
const a = asFiniteNumber(5.5);
|
|
63
|
+
const b = asFiniteNumber(2.5);
|
|
64
|
+
const c = asFiniteNumber(-3.5);
|
|
65
|
+
|
|
66
|
+
test('abs', () => {
|
|
67
|
+
expect(FiniteNumber.abs(a)).toBe(5.5);
|
|
68
|
+
expect(FiniteNumber.abs(c)).toBe(3.5);
|
|
69
|
+
expect(FiniteNumber.abs(asFiniteNumber(0))).toBe(0);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('min and max', () => {
|
|
73
|
+
expect(FiniteNumber.min(a, b)).toBe(2.5);
|
|
74
|
+
expect(FiniteNumber.max(a, b)).toBe(5.5);
|
|
75
|
+
expect(FiniteNumber.min(a, c)).toBe(-3.5);
|
|
76
|
+
expect(FiniteNumber.max(a, c)).toBe(5.5);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('floor, ceil, round', () => {
|
|
80
|
+
expect(FiniteNumber.floor(a)).toBe(5);
|
|
81
|
+
expect(FiniteNumber.ceil(a)).toBe(6);
|
|
82
|
+
expect(FiniteNumber.round(a)).toBe(6);
|
|
83
|
+
expect(FiniteNumber.floor(c)).toBe(-4);
|
|
84
|
+
expect(FiniteNumber.ceil(c)).toBe(-3);
|
|
85
|
+
expect(FiniteNumber.round(c)).toBe(-3);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test('add', () => {
|
|
89
|
+
expect(FiniteNumber.add(a, b)).toBe(8);
|
|
90
|
+
expect(FiniteNumber.add(a, c)).toBe(2);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test('sub', () => {
|
|
94
|
+
expect(FiniteNumber.sub(a, b)).toBe(3);
|
|
95
|
+
expect(FiniteNumber.sub(a, c)).toBe(9);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
test('mul', () => {
|
|
99
|
+
expect(FiniteNumber.mul(a, b)).toBe(13.75);
|
|
100
|
+
expect(FiniteNumber.mul(a, c)).toBe(-19.25);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
test('div', () => {
|
|
104
|
+
expect(FiniteNumber.div(a, asNonZeroFiniteNumber(2.5))).toBe(2.2);
|
|
105
|
+
expect(FiniteNumber.div(a, asNonZeroFiniteNumber(2))).toBe(2.75);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test('pow', () => {
|
|
109
|
+
expect(FiniteNumber.pow(asFiniteNumber(2), asFiniteNumber(3))).toBe(8);
|
|
110
|
+
expect(FiniteNumber.pow(asFiniteNumber(3), asFiniteNumber(2))).toBe(9);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe('random', () => {
|
|
115
|
+
test('generates numbers within specified range', () => {
|
|
116
|
+
const min = asFiniteNumber(-5.5);
|
|
117
|
+
const max = asFiniteNumber(10.3);
|
|
118
|
+
|
|
119
|
+
for (let i = 0; i < 10; i++) {
|
|
120
|
+
const result = FiniteNumber.random(min, max);
|
|
121
|
+
expect(result).toBeGreaterThanOrEqual(min);
|
|
122
|
+
expect(result).toBeLessThanOrEqual(max);
|
|
123
|
+
expect(FiniteNumber.is(result)).toBe(true);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('type assertions', () => {
|
|
129
|
+
test('type relationships', () => {
|
|
130
|
+
expectType<FiniteNumber, number>('<=');
|
|
131
|
+
|
|
132
|
+
expectTypeOf(asFiniteNumber(5.5)).toExtend<FiniteNumber>();
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export * from './finite-number.mjs';
|
|
2
|
+
export * from './int.mjs';
|
|
3
|
+
export * from './int16.mjs';
|
|
4
|
+
export * from './int32.mjs';
|
|
5
|
+
export * from './non-negative-finite-number.mjs';
|
|
6
|
+
export * from './non-negative-int16.mjs';
|
|
7
|
+
export * from './non-negative-int32.mjs';
|
|
8
|
+
export * from './non-zero-finite-number.mjs';
|
|
9
|
+
export * from './non-zero-int.mjs';
|
|
10
|
+
export * from './non-zero-int16.mjs';
|
|
11
|
+
export * from './non-zero-int32.mjs';
|
|
12
|
+
export * from './non-zero-safe-int.mjs';
|
|
13
|
+
export * from './non-zero-uint16.mjs';
|
|
14
|
+
export * from './non-zero-uint32.mjs';
|
|
15
|
+
export * from './positive-finite-number.mjs';
|
|
16
|
+
export * from './positive-int.mjs';
|
|
17
|
+
export * from './positive-int16.mjs';
|
|
18
|
+
export * from './positive-int32.mjs';
|
|
19
|
+
export * from './positive-safe-int.mjs';
|
|
20
|
+
export * from './positive-uint16.mjs';
|
|
21
|
+
export * from './positive-uint32.mjs';
|
|
22
|
+
export * from './safe-int.mjs';
|
|
23
|
+
export * from './safe-uint.mjs';
|
|
24
|
+
export * from './uint.mjs';
|
|
25
|
+
export * from './uint16.mjs';
|
|
26
|
+
export * from './uint32.mjs';
|