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,188 @@
|
|
|
1
|
+
import { expectType } from '../../expect-type.mjs';
|
|
2
|
+
import { TsVerifiedInternals } from '../refined-number-utils.mjs';
|
|
3
|
+
|
|
4
|
+
type ElementType = PositiveInt16;
|
|
5
|
+
|
|
6
|
+
const typeNameInMessage = 'a positive integer in [1, 2^15)';
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
MIN_VALUE,
|
|
10
|
+
MAX_VALUE,
|
|
11
|
+
min: min_,
|
|
12
|
+
max: max_,
|
|
13
|
+
pow,
|
|
14
|
+
add,
|
|
15
|
+
sub,
|
|
16
|
+
mul,
|
|
17
|
+
div,
|
|
18
|
+
random,
|
|
19
|
+
is,
|
|
20
|
+
castType,
|
|
21
|
+
clamp,
|
|
22
|
+
} = TsVerifiedInternals.RefinedNumberUtils.operatorsForInteger<
|
|
23
|
+
ElementType,
|
|
24
|
+
1,
|
|
25
|
+
number
|
|
26
|
+
>({
|
|
27
|
+
integerOrSafeInteger: 'SafeInteger',
|
|
28
|
+
MIN_VALUE: 1,
|
|
29
|
+
MAX_VALUE: 2 ** 15 - 1,
|
|
30
|
+
typeNameInMessage,
|
|
31
|
+
} as const);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Checks if a number is a PositiveInt16 (16-bit positive signed integer in the range [1, 2^15)).
|
|
35
|
+
* @param value The value to check.
|
|
36
|
+
* @returns `true` if the value is a PositiveInt16, `false` otherwise.
|
|
37
|
+
*/
|
|
38
|
+
export const isPositiveInt16 = is;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Casts a number to a PositiveInt16 type.
|
|
42
|
+
* @param value The value to cast.
|
|
43
|
+
* @returns The value as a PositiveInt16 type.
|
|
44
|
+
* @throws {TypeError} If the value is not a positive integer in [1, 2^15).
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const x = asPositiveInt16(1000); // PositiveInt16
|
|
48
|
+
* const y = asPositiveInt16(32767); // PositiveInt16
|
|
49
|
+
* // asPositiveInt16(0); // throws TypeError
|
|
50
|
+
* // asPositiveInt16(-1); // throws TypeError
|
|
51
|
+
* // asPositiveInt16(32768); // throws TypeError
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export const asPositiveInt16 = castType;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Namespace providing type-safe arithmetic operations for 16-bit positive integers.
|
|
58
|
+
*
|
|
59
|
+
* All operations automatically clamp results to the valid PositiveInt16 range [1, 32767].
|
|
60
|
+
* This ensures that all arithmetic maintains the 16-bit positive integer constraint,
|
|
61
|
+
* with results below 1 clamped to MIN_VALUE and overflow results clamped to MAX_VALUE.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* const a = asPositiveInt16(30000);
|
|
66
|
+
* const b = asPositiveInt16(5000);
|
|
67
|
+
*
|
|
68
|
+
* // Arithmetic operations with automatic clamping
|
|
69
|
+
* const sum = PositiveInt16.add(a, b); // PositiveInt16 (32767 - clamped to MAX_VALUE)
|
|
70
|
+
* const diff = PositiveInt16.sub(a, b); // PositiveInt16 (25000)
|
|
71
|
+
* const reverseDiff = PositiveInt16.sub(b, a); // PositiveInt16 (1 - clamped to MIN_VALUE)
|
|
72
|
+
* const product = PositiveInt16.mul(a, b); // PositiveInt16 (32767 - clamped due to overflow)
|
|
73
|
+
*
|
|
74
|
+
* // Range operations
|
|
75
|
+
* const clamped = PositiveInt16.clamp(0); // PositiveInt16 (1)
|
|
76
|
+
* const minimum = PositiveInt16.min(a, b); // PositiveInt16 (5000)
|
|
77
|
+
* const maximum = PositiveInt16.max(a, b); // PositiveInt16 (30000)
|
|
78
|
+
*
|
|
79
|
+
* // Utility operations
|
|
80
|
+
* const random = PositiveInt16.random(); // PositiveInt16 (random value in [1, 32767])
|
|
81
|
+
* const power = PositiveInt16.pow(asPositiveInt16(2), asPositiveInt16(10)); // PositiveInt16 (1024)
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export const PositiveInt16 = {
|
|
85
|
+
/**
|
|
86
|
+
* Type guard to check if a value is a PositiveInt16.
|
|
87
|
+
* @param value The value to check.
|
|
88
|
+
* @returns `true` if the value is a 16-bit positive integer, `false` otherwise.
|
|
89
|
+
*/
|
|
90
|
+
is,
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The minimum value for a 16-bit positive integer.
|
|
94
|
+
* @readonly
|
|
95
|
+
*/
|
|
96
|
+
MIN_VALUE,
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The maximum value for a 16-bit positive integer.
|
|
100
|
+
* @readonly
|
|
101
|
+
*/
|
|
102
|
+
MAX_VALUE,
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Returns the smaller of two PositiveInt16 values.
|
|
106
|
+
* @param a The first PositiveInt16.
|
|
107
|
+
* @param b The second PositiveInt16.
|
|
108
|
+
* @returns The minimum value as a PositiveInt16.
|
|
109
|
+
*/
|
|
110
|
+
min: min_,
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Returns the larger of two PositiveInt16 values.
|
|
114
|
+
* @param a The first PositiveInt16.
|
|
115
|
+
* @param b The second PositiveInt16.
|
|
116
|
+
* @returns The maximum value as a PositiveInt16.
|
|
117
|
+
*/
|
|
118
|
+
max: max_,
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Clamps a number to the PositiveInt16 range.
|
|
122
|
+
* @param value The number to clamp.
|
|
123
|
+
* @returns The value clamped to [1, 32767] as a PositiveInt16.
|
|
124
|
+
*/
|
|
125
|
+
clamp,
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Generates a random PositiveInt16 value within the valid range.
|
|
129
|
+
* @returns A random PositiveInt16 between 1 and 32767.
|
|
130
|
+
*/
|
|
131
|
+
random,
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Raises a PositiveInt16 to the power of another PositiveInt16.
|
|
135
|
+
* @param a The base PositiveInt16.
|
|
136
|
+
* @param b The exponent PositiveInt16.
|
|
137
|
+
* @returns `a ** b` clamped to [1, 32767] as a PositiveInt16.
|
|
138
|
+
*/
|
|
139
|
+
pow,
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Adds two PositiveInt16 values.
|
|
143
|
+
* @param a The first PositiveInt16.
|
|
144
|
+
* @param b The second PositiveInt16.
|
|
145
|
+
* @returns `a + b` clamped to [1, 32767] as a PositiveInt16.
|
|
146
|
+
*/
|
|
147
|
+
add,
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Subtracts one PositiveInt16 from another.
|
|
151
|
+
* @param a The minuend PositiveInt16.
|
|
152
|
+
* @param b The subtrahend PositiveInt16.
|
|
153
|
+
* @returns `a - b` clamped to [1, 32767] as a PositiveInt16 (minimum 1).
|
|
154
|
+
*/
|
|
155
|
+
sub,
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Multiplies two PositiveInt16 values.
|
|
159
|
+
* @param a The first PositiveInt16.
|
|
160
|
+
* @param b The second PositiveInt16.
|
|
161
|
+
* @returns `a * b` clamped to [1, 32767] as a PositiveInt16.
|
|
162
|
+
*/
|
|
163
|
+
mul,
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Divides one PositiveInt16 by another using floor division.
|
|
167
|
+
* @param a The dividend PositiveInt16.
|
|
168
|
+
* @param b The divisor PositiveInt16.
|
|
169
|
+
* @returns `⌊a / b⌋` clamped to [1, 32767] as a PositiveInt16.
|
|
170
|
+
*/
|
|
171
|
+
div,
|
|
172
|
+
} as const;
|
|
173
|
+
|
|
174
|
+
expectType<
|
|
175
|
+
keyof typeof PositiveInt16,
|
|
176
|
+
keyof TsVerifiedInternals.RefinedNumberUtils.NumberClass<
|
|
177
|
+
ElementType,
|
|
178
|
+
'int' | 'positive' | 'range'
|
|
179
|
+
>
|
|
180
|
+
>('=');
|
|
181
|
+
|
|
182
|
+
expectType<
|
|
183
|
+
typeof PositiveInt16,
|
|
184
|
+
TsVerifiedInternals.RefinedNumberUtils.NumberClass<
|
|
185
|
+
ElementType,
|
|
186
|
+
'int' | 'positive' | 'range'
|
|
187
|
+
>
|
|
188
|
+
>('<=');
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { expectType } from '../../expect-type.mjs';
|
|
2
|
+
import {
|
|
3
|
+
asPositiveInt16,
|
|
4
|
+
isPositiveInt16,
|
|
5
|
+
PositiveInt16,
|
|
6
|
+
} from './positive-int16.mjs';
|
|
7
|
+
|
|
8
|
+
describe('PositiveInt16', () => {
|
|
9
|
+
describe('asPositiveInt16', () => {
|
|
10
|
+
test('accepts valid positive int16 values', () => {
|
|
11
|
+
expect(() => asPositiveInt16(1)).not.toThrow();
|
|
12
|
+
expect(() => asPositiveInt16(1000)).not.toThrow();
|
|
13
|
+
expect(() => asPositiveInt16(32767)).not.toThrow(); // 2^15 - 1
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('rejects zero', () => {
|
|
17
|
+
expect(() => asPositiveInt16(0)).toThrow(TypeError);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('rejects values outside int16 range', () => {
|
|
21
|
+
expect(() => asPositiveInt16(32768)).toThrow(TypeError); // 2^15
|
|
22
|
+
expect(() => asPositiveInt16(65536)).toThrow(TypeError);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test('rejects negative integers', () => {
|
|
26
|
+
expect(() => asPositiveInt16(-1)).toThrow(TypeError);
|
|
27
|
+
expect(() => asPositiveInt16(-42)).toThrow(TypeError);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test('rejects non-integers', () => {
|
|
31
|
+
expect(() => asPositiveInt16(Number.NaN)).toThrow(TypeError);
|
|
32
|
+
expect(() => asPositiveInt16(Number.POSITIVE_INFINITY)).toThrow(
|
|
33
|
+
TypeError,
|
|
34
|
+
);
|
|
35
|
+
expect(() => asPositiveInt16(Number.NEGATIVE_INFINITY)).toThrow(
|
|
36
|
+
TypeError,
|
|
37
|
+
);
|
|
38
|
+
expect(() => asPositiveInt16(1.2)).toThrow(TypeError);
|
|
39
|
+
expect(() => asPositiveInt16(-3.4)).toThrow(TypeError);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
test('returns the same value for valid inputs', () => {
|
|
43
|
+
expect(asPositiveInt16(5)).toBe(5);
|
|
44
|
+
expect(asPositiveInt16(1)).toBe(1);
|
|
45
|
+
expect(asPositiveInt16(32767)).toBe(32767);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test.each([
|
|
49
|
+
{ name: 'Number.NaN', value: Number.NaN },
|
|
50
|
+
{ name: 'Number.POSITIVE_INFINITY', value: Number.POSITIVE_INFINITY },
|
|
51
|
+
{ name: 'Number.NEGATIVE_INFINITY', value: Number.NEGATIVE_INFINITY },
|
|
52
|
+
{ name: '1.2', value: 1.2 },
|
|
53
|
+
{ name: '-3.4', value: -3.4 },
|
|
54
|
+
{ name: '0', value: 0 },
|
|
55
|
+
{ name: '-1', value: -1 },
|
|
56
|
+
{ name: '32768', value: 32768 },
|
|
57
|
+
] as const)(
|
|
58
|
+
`asPositiveInt16($name) should throw a TypeError`,
|
|
59
|
+
({ value }) => {
|
|
60
|
+
expect(() => asPositiveInt16(value)).toThrow(
|
|
61
|
+
new TypeError(
|
|
62
|
+
`Expected a positive integer in [1, 2^15), got: ${value}`,
|
|
63
|
+
),
|
|
64
|
+
);
|
|
65
|
+
},
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
describe('isPositiveInt16', () => {
|
|
70
|
+
test('correctly identifies positive int16 values', () => {
|
|
71
|
+
expect(isPositiveInt16(1)).toBe(true);
|
|
72
|
+
expect(isPositiveInt16(1000)).toBe(true);
|
|
73
|
+
expect(isPositiveInt16(32767)).toBe(true);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test('correctly identifies zero', () => {
|
|
77
|
+
expect(isPositiveInt16(0)).toBe(false);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test('correctly identifies values outside int16 range', () => {
|
|
81
|
+
expect(isPositiveInt16(32768)).toBe(false);
|
|
82
|
+
expect(isPositiveInt16(65536)).toBe(false);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('correctly identifies negative integers', () => {
|
|
86
|
+
expect(isPositiveInt16(-1)).toBe(false);
|
|
87
|
+
expect(isPositiveInt16(-42)).toBe(false);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test('correctly identifies non-integers', () => {
|
|
91
|
+
expect(isPositiveInt16(Number.NaN)).toBe(false);
|
|
92
|
+
expect(isPositiveInt16(Number.POSITIVE_INFINITY)).toBe(false);
|
|
93
|
+
expect(isPositiveInt16(Number.NEGATIVE_INFINITY)).toBe(false);
|
|
94
|
+
expect(isPositiveInt16(1.2)).toBe(false);
|
|
95
|
+
expect(isPositiveInt16(-3.4)).toBe(false);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe('PositiveInt16.is', () => {
|
|
100
|
+
test('same as isPositiveInt16 function', () => {
|
|
101
|
+
expect(PositiveInt16.is(5)).toBe(isPositiveInt16(5));
|
|
102
|
+
expect(PositiveInt16.is(0)).toBe(isPositiveInt16(0));
|
|
103
|
+
expect(PositiveInt16.is(-1)).toBe(isPositiveInt16(-1));
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
describe('constants', () => {
|
|
108
|
+
test('MIN_VALUE and MAX_VALUE', () => {
|
|
109
|
+
expect(PositiveInt16.MIN_VALUE).toBe(1);
|
|
110
|
+
expect(PositiveInt16.MAX_VALUE).toBe(32767);
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
describe('mathematical operations', () => {
|
|
115
|
+
const a = asPositiveInt16(100);
|
|
116
|
+
const b = asPositiveInt16(50);
|
|
117
|
+
|
|
118
|
+
test('min and max', () => {
|
|
119
|
+
expect(PositiveInt16.min(a, b)).toBe(50);
|
|
120
|
+
expect(PositiveInt16.max(a, b)).toBe(100);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test('add (with clamping to positive int16 range)', () => {
|
|
124
|
+
const result = PositiveInt16.add(
|
|
125
|
+
asPositiveInt16(32000),
|
|
126
|
+
asPositiveInt16(1000),
|
|
127
|
+
);
|
|
128
|
+
expect(result).toBe(32767); // clamped to max
|
|
129
|
+
expect(PositiveInt16.add(a, b)).toBe(150);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test('sub (never goes below 1)', () => {
|
|
133
|
+
expect(PositiveInt16.sub(a, b)).toBe(50);
|
|
134
|
+
expect(PositiveInt16.sub(b, a)).toBe(1); // clamped to 1
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test('mul (with clamping to positive int16 range)', () => {
|
|
138
|
+
const result = PositiveInt16.mul(
|
|
139
|
+
asPositiveInt16(1000),
|
|
140
|
+
asPositiveInt16(100),
|
|
141
|
+
);
|
|
142
|
+
expect(result).toBe(32767); // clamped to max
|
|
143
|
+
expect(PositiveInt16.mul(asPositiveInt16(10), asPositiveInt16(5))).toBe(
|
|
144
|
+
50,
|
|
145
|
+
);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test('div (floor division, never goes below 1)', () => {
|
|
149
|
+
expect(PositiveInt16.div(a, asPositiveInt16(50))).toBe(2);
|
|
150
|
+
expect(PositiveInt16.div(asPositiveInt16(7), asPositiveInt16(3))).toBe(2);
|
|
151
|
+
expect(PositiveInt16.div(asPositiveInt16(50), asPositiveInt16(100))).toBe(
|
|
152
|
+
1,
|
|
153
|
+
); // floor(50/100) = 0, clamped to 1
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test('pow (with clamping to positive int16 range)', () => {
|
|
157
|
+
const result = PositiveInt16.pow(
|
|
158
|
+
asPositiveInt16(200),
|
|
159
|
+
asPositiveInt16(3),
|
|
160
|
+
);
|
|
161
|
+
expect(result).toBe(32767); // clamped to max
|
|
162
|
+
expect(PositiveInt16.pow(asPositiveInt16(2), asPositiveInt16(3))).toBe(8);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
describe('random', () => {
|
|
167
|
+
test('generates positive int16 values within specified range', () => {
|
|
168
|
+
const min = 1;
|
|
169
|
+
const max = 20;
|
|
170
|
+
|
|
171
|
+
for (let i = 0; i < 10; i++) {
|
|
172
|
+
const result = PositiveInt16.random(min, max);
|
|
173
|
+
expect(result).toBeGreaterThanOrEqual(min);
|
|
174
|
+
expect(result).toBeLessThanOrEqual(max);
|
|
175
|
+
expect(PositiveInt16.is(result)).toBe(true);
|
|
176
|
+
expect(Number.isInteger(result)).toBe(true);
|
|
177
|
+
expect(result).toBeGreaterThan(0);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test('generates values within PositiveInt16 range', () => {
|
|
182
|
+
for (let i = 0; i < 10; i++) {
|
|
183
|
+
const result = PositiveInt16.random(1, 30);
|
|
184
|
+
expect(result).toBeGreaterThanOrEqual(1);
|
|
185
|
+
expect(result).toBeLessThanOrEqual(32767);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
describe('type assertions', () => {
|
|
191
|
+
test('type relationships', () => {
|
|
192
|
+
expectType<PositiveInt16, number>('<=');
|
|
193
|
+
|
|
194
|
+
expectTypeOf(asPositiveInt16(100)).toExtend<PositiveInt16>();
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
});
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import { expectType } from '../../expect-type.mjs';
|
|
2
|
+
import { TsVerifiedInternals } from '../refined-number-utils.mjs';
|
|
3
|
+
|
|
4
|
+
type ElementType = PositiveInt32;
|
|
5
|
+
|
|
6
|
+
const typeNameInMessage = 'a positive integer in [1, 2^31)';
|
|
7
|
+
|
|
8
|
+
const {
|
|
9
|
+
MIN_VALUE,
|
|
10
|
+
MAX_VALUE,
|
|
11
|
+
min: min_,
|
|
12
|
+
max: max_,
|
|
13
|
+
pow,
|
|
14
|
+
add,
|
|
15
|
+
sub,
|
|
16
|
+
mul,
|
|
17
|
+
div,
|
|
18
|
+
random,
|
|
19
|
+
is,
|
|
20
|
+
castType,
|
|
21
|
+
clamp,
|
|
22
|
+
} = TsVerifiedInternals.RefinedNumberUtils.operatorsForInteger<
|
|
23
|
+
ElementType,
|
|
24
|
+
1,
|
|
25
|
+
number
|
|
26
|
+
>({
|
|
27
|
+
integerOrSafeInteger: 'SafeInteger',
|
|
28
|
+
MIN_VALUE: 1,
|
|
29
|
+
MAX_VALUE: 2 ** 31 - 1,
|
|
30
|
+
typeNameInMessage,
|
|
31
|
+
} as const);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Checks if a number is a PositiveInt32 (32-bit positive signed integer in the range [1, 2^31)).
|
|
35
|
+
* @param value The value to check.
|
|
36
|
+
* @returns `true` if the value is a PositiveInt32, `false` otherwise.
|
|
37
|
+
*/
|
|
38
|
+
export const isPositiveInt32 = is;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Casts a number to a PositiveInt32 type.
|
|
42
|
+
* @param value The value to cast.
|
|
43
|
+
* @returns The value as a PositiveInt32 type.
|
|
44
|
+
* @throws {TypeError} If the value is not a positive integer in [1, 2^31).
|
|
45
|
+
* @example
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const x = asPositiveInt32(1000); // PositiveInt32
|
|
48
|
+
* const y = asPositiveInt32(2147483647); // PositiveInt32
|
|
49
|
+
* // asPositiveInt32(0); // throws TypeError
|
|
50
|
+
* // asPositiveInt32(-1); // throws TypeError
|
|
51
|
+
* // asPositiveInt32(2147483648); // throws TypeError
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export const asPositiveInt32 = castType;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Namespace providing type-safe arithmetic operations for 32-bit positive integers.
|
|
58
|
+
*
|
|
59
|
+
* All operations automatically clamp results to the valid PositiveInt32 range [1, 2147483647].
|
|
60
|
+
* This ensures that all arithmetic maintains the 32-bit positive integer constraint,
|
|
61
|
+
* with results below 1 clamped to MIN_VALUE and overflow results clamped to MAX_VALUE.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* const a = asPositiveInt32(2000000000);
|
|
66
|
+
* const b = asPositiveInt32(500000000);
|
|
67
|
+
*
|
|
68
|
+
* // Arithmetic operations with automatic clamping and positive constraint
|
|
69
|
+
* const sum = PositiveInt32.add(a, b); // PositiveInt32 (2147483647 - clamped to MAX_VALUE)
|
|
70
|
+
* const diff = PositiveInt32.sub(a, b); // PositiveInt32 (1500000000)
|
|
71
|
+
* const reverseDiff = PositiveInt32.sub(b, a); // PositiveInt32 (1 - clamped to MIN_VALUE)
|
|
72
|
+
* const product = PositiveInt32.mul(a, b); // PositiveInt32 (2147483647 - clamped due to overflow)
|
|
73
|
+
*
|
|
74
|
+
* // Range operations (maintaining positive constraint)
|
|
75
|
+
* const clamped = PositiveInt32.clamp(-1000); // PositiveInt32 (1)
|
|
76
|
+
* const minimum = PositiveInt32.min(a, b); // PositiveInt32 (500000000)
|
|
77
|
+
* const maximum = PositiveInt32.max(a, b); // PositiveInt32 (2000000000)
|
|
78
|
+
*
|
|
79
|
+
* // Utility operations
|
|
80
|
+
* const random = PositiveInt32.random(); // PositiveInt32 (random value in [1, 2147483647])
|
|
81
|
+
* const power = PositiveInt32.pow(asPositiveInt32(2), asPositiveInt32(20)); // PositiveInt32 (1048576)
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export const PositiveInt32 = {
|
|
85
|
+
/**
|
|
86
|
+
* Type guard to check if a value is a PositiveInt32.
|
|
87
|
+
* @param value The value to check.
|
|
88
|
+
* @returns `true` if the value is a 32-bit positive integer, `false` otherwise.
|
|
89
|
+
*/
|
|
90
|
+
is,
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* The minimum value for a 32-bit positive integer.
|
|
94
|
+
* @readonly
|
|
95
|
+
*/
|
|
96
|
+
MIN_VALUE,
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The maximum value for a 32-bit positive integer.
|
|
100
|
+
* @readonly
|
|
101
|
+
*/
|
|
102
|
+
MAX_VALUE,
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Returns the smaller of two PositiveInt32 values.
|
|
106
|
+
* @param a The first PositiveInt32.
|
|
107
|
+
* @param b The second PositiveInt32.
|
|
108
|
+
* @returns The minimum value as a PositiveInt32.
|
|
109
|
+
*/
|
|
110
|
+
min: min_,
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Returns the larger of two PositiveInt32 values.
|
|
114
|
+
* @param a The first PositiveInt32.
|
|
115
|
+
* @param b The second PositiveInt32.
|
|
116
|
+
* @returns The maximum value as a PositiveInt32.
|
|
117
|
+
*/
|
|
118
|
+
max: max_,
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Clamps a number to the PositiveInt32 range.
|
|
122
|
+
* @param value The number to clamp.
|
|
123
|
+
* @returns The value clamped to [1, 2147483647] as a PositiveInt32.
|
|
124
|
+
*/
|
|
125
|
+
clamp,
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Generates a random PositiveInt32 value within the valid range.
|
|
129
|
+
* @returns A random PositiveInt32 between 1 and 2147483647.
|
|
130
|
+
*/
|
|
131
|
+
random,
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Raises a PositiveInt32 to the power of another PositiveInt32.
|
|
135
|
+
* @param a The base PositiveInt32.
|
|
136
|
+
* @param b The exponent PositiveInt32.
|
|
137
|
+
* @returns `a ** b` clamped to [1, 2147483647] as a PositiveInt32.
|
|
138
|
+
*/
|
|
139
|
+
pow,
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Adds two PositiveInt32 values.
|
|
143
|
+
* @param a The first PositiveInt32.
|
|
144
|
+
* @param b The second PositiveInt32.
|
|
145
|
+
* @returns `a + b` clamped to [1, 2147483647] as a PositiveInt32.
|
|
146
|
+
*/
|
|
147
|
+
add,
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Subtracts one PositiveInt32 from another.
|
|
151
|
+
* @param a The minuend PositiveInt32.
|
|
152
|
+
* @param b The subtrahend PositiveInt32.
|
|
153
|
+
* @returns `a - b` clamped to [1, 2147483647] as a PositiveInt32 (minimum 1).
|
|
154
|
+
*/
|
|
155
|
+
sub,
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Multiplies two PositiveInt32 values.
|
|
159
|
+
* @param a The first PositiveInt32.
|
|
160
|
+
* @param b The second PositiveInt32.
|
|
161
|
+
* @returns `a * b` clamped to [1, 2147483647] as a PositiveInt32.
|
|
162
|
+
*/
|
|
163
|
+
mul,
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Divides one PositiveInt32 by another using floor division.
|
|
167
|
+
* @param a The dividend PositiveInt32.
|
|
168
|
+
* @param b The divisor PositiveInt32.
|
|
169
|
+
* @returns `⌊a / b⌋` clamped to [1, 2147483647] as a PositiveInt32.
|
|
170
|
+
*/
|
|
171
|
+
div,
|
|
172
|
+
} as const;
|
|
173
|
+
|
|
174
|
+
expectType<
|
|
175
|
+
keyof typeof PositiveInt32,
|
|
176
|
+
keyof TsVerifiedInternals.RefinedNumberUtils.NumberClass<
|
|
177
|
+
ElementType,
|
|
178
|
+
'int' | 'positive' | 'range'
|
|
179
|
+
>
|
|
180
|
+
>('=');
|
|
181
|
+
|
|
182
|
+
expectType<
|
|
183
|
+
typeof PositiveInt32,
|
|
184
|
+
TsVerifiedInternals.RefinedNumberUtils.NumberClass<
|
|
185
|
+
ElementType,
|
|
186
|
+
'int' | 'positive' | 'range'
|
|
187
|
+
>
|
|
188
|
+
>('<=');
|