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.
Files changed (143) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +534 -0
  3. package/package.json +101 -0
  4. package/src/array/array-utils-creation.test.mts +443 -0
  5. package/src/array/array-utils-modification.test.mts +197 -0
  6. package/src/array/array-utils-overload-type-error.test.mts +149 -0
  7. package/src/array/array-utils-reducing-value.test.mts +425 -0
  8. package/src/array/array-utils-search.test.mts +169 -0
  9. package/src/array/array-utils-set-op.test.mts +335 -0
  10. package/src/array/array-utils-slice-clamped.test.mts +113 -0
  11. package/src/array/array-utils-slicing.test.mts +316 -0
  12. package/src/array/array-utils-transformation.test.mts +790 -0
  13. package/src/array/array-utils-validation.test.mts +492 -0
  14. package/src/array/array-utils.mts +4000 -0
  15. package/src/array/array.test.mts +146 -0
  16. package/src/array/index.mts +2 -0
  17. package/src/array/tuple-utils.mts +519 -0
  18. package/src/array/tuple-utils.test.mts +518 -0
  19. package/src/collections/imap-mapped.mts +801 -0
  20. package/src/collections/imap-mapped.test.mts +860 -0
  21. package/src/collections/imap.mts +651 -0
  22. package/src/collections/imap.test.mts +932 -0
  23. package/src/collections/index.mts +6 -0
  24. package/src/collections/iset-mapped.mts +889 -0
  25. package/src/collections/iset-mapped.test.mts +1187 -0
  26. package/src/collections/iset.mts +682 -0
  27. package/src/collections/iset.test.mts +1084 -0
  28. package/src/collections/queue.mts +390 -0
  29. package/src/collections/queue.test.mts +282 -0
  30. package/src/collections/stack.mts +423 -0
  31. package/src/collections/stack.test.mts +225 -0
  32. package/src/expect-type.mts +206 -0
  33. package/src/functional/index.mts +4 -0
  34. package/src/functional/match.mts +300 -0
  35. package/src/functional/match.test.mts +177 -0
  36. package/src/functional/optional.mts +733 -0
  37. package/src/functional/optional.test.mts +619 -0
  38. package/src/functional/pipe.mts +212 -0
  39. package/src/functional/pipe.test.mts +85 -0
  40. package/src/functional/result.mts +1134 -0
  41. package/src/functional/result.test.mts +777 -0
  42. package/src/globals.d.mts +38 -0
  43. package/src/guard/has-key.mts +119 -0
  44. package/src/guard/has-key.test.mts +219 -0
  45. package/src/guard/index.mts +7 -0
  46. package/src/guard/is-non-empty-string.mts +108 -0
  47. package/src/guard/is-non-empty-string.test.mts +91 -0
  48. package/src/guard/is-non-null-object.mts +106 -0
  49. package/src/guard/is-non-null-object.test.mts +90 -0
  50. package/src/guard/is-primitive.mts +165 -0
  51. package/src/guard/is-primitive.test.mts +102 -0
  52. package/src/guard/is-record.mts +153 -0
  53. package/src/guard/is-record.test.mts +112 -0
  54. package/src/guard/is-type.mts +450 -0
  55. package/src/guard/is-type.test.mts +496 -0
  56. package/src/guard/key-is-in.mts +163 -0
  57. package/src/guard/key-is-in.test.mts +19 -0
  58. package/src/index.mts +10 -0
  59. package/src/iterator/index.mts +1 -0
  60. package/src/iterator/range.mts +120 -0
  61. package/src/iterator/range.test.mts +33 -0
  62. package/src/json/index.mts +1 -0
  63. package/src/json/json.mts +711 -0
  64. package/src/json/json.test.mts +628 -0
  65. package/src/number/branded-types/finite-number.mts +354 -0
  66. package/src/number/branded-types/finite-number.test.mts +135 -0
  67. package/src/number/branded-types/index.mts +26 -0
  68. package/src/number/branded-types/int.mts +278 -0
  69. package/src/number/branded-types/int.test.mts +140 -0
  70. package/src/number/branded-types/int16.mts +192 -0
  71. package/src/number/branded-types/int16.test.mts +170 -0
  72. package/src/number/branded-types/int32.mts +193 -0
  73. package/src/number/branded-types/int32.test.mts +170 -0
  74. package/src/number/branded-types/non-negative-finite-number.mts +223 -0
  75. package/src/number/branded-types/non-negative-finite-number.test.mts +188 -0
  76. package/src/number/branded-types/non-negative-int16.mts +187 -0
  77. package/src/number/branded-types/non-negative-int16.test.mts +201 -0
  78. package/src/number/branded-types/non-negative-int32.mts +187 -0
  79. package/src/number/branded-types/non-negative-int32.test.mts +204 -0
  80. package/src/number/branded-types/non-zero-finite-number.mts +229 -0
  81. package/src/number/branded-types/non-zero-finite-number.test.mts +198 -0
  82. package/src/number/branded-types/non-zero-int.mts +167 -0
  83. package/src/number/branded-types/non-zero-int.test.mts +177 -0
  84. package/src/number/branded-types/non-zero-int16.mts +196 -0
  85. package/src/number/branded-types/non-zero-int16.test.mts +195 -0
  86. package/src/number/branded-types/non-zero-int32.mts +196 -0
  87. package/src/number/branded-types/non-zero-int32.test.mts +197 -0
  88. package/src/number/branded-types/non-zero-safe-int.mts +196 -0
  89. package/src/number/branded-types/non-zero-safe-int.test.mts +232 -0
  90. package/src/number/branded-types/non-zero-uint16.mts +189 -0
  91. package/src/number/branded-types/non-zero-uint16.test.mts +199 -0
  92. package/src/number/branded-types/non-zero-uint32.mts +189 -0
  93. package/src/number/branded-types/non-zero-uint32.test.mts +199 -0
  94. package/src/number/branded-types/positive-finite-number.mts +241 -0
  95. package/src/number/branded-types/positive-finite-number.test.mts +204 -0
  96. package/src/number/branded-types/positive-int.mts +304 -0
  97. package/src/number/branded-types/positive-int.test.mts +176 -0
  98. package/src/number/branded-types/positive-int16.mts +188 -0
  99. package/src/number/branded-types/positive-int16.test.mts +197 -0
  100. package/src/number/branded-types/positive-int32.mts +188 -0
  101. package/src/number/branded-types/positive-int32.test.mts +197 -0
  102. package/src/number/branded-types/positive-safe-int.mts +187 -0
  103. package/src/number/branded-types/positive-safe-int.test.mts +210 -0
  104. package/src/number/branded-types/positive-uint16.mts +188 -0
  105. package/src/number/branded-types/positive-uint16.test.mts +203 -0
  106. package/src/number/branded-types/positive-uint32.mts +188 -0
  107. package/src/number/branded-types/positive-uint32.test.mts +203 -0
  108. package/src/number/branded-types/safe-int.mts +291 -0
  109. package/src/number/branded-types/safe-int.test.mts +170 -0
  110. package/src/number/branded-types/safe-uint.mts +187 -0
  111. package/src/number/branded-types/safe-uint.test.mts +176 -0
  112. package/src/number/branded-types/uint.mts +179 -0
  113. package/src/number/branded-types/uint.test.mts +158 -0
  114. package/src/number/branded-types/uint16.mts +186 -0
  115. package/src/number/branded-types/uint16.test.mts +170 -0
  116. package/src/number/branded-types/uint32.mts +218 -0
  117. package/src/number/branded-types/uint32.test.mts +170 -0
  118. package/src/number/enum/index.mts +2 -0
  119. package/src/number/enum/int8.mts +344 -0
  120. package/src/number/enum/int8.test.mts +180 -0
  121. package/src/number/enum/uint8.mts +293 -0
  122. package/src/number/enum/uint8.test.mts +164 -0
  123. package/src/number/index.mts +4 -0
  124. package/src/number/num.mts +604 -0
  125. package/src/number/num.test.mts +242 -0
  126. package/src/number/refined-number-utils.mts +566 -0
  127. package/src/object/index.mts +1 -0
  128. package/src/object/object.mts +447 -0
  129. package/src/object/object.test.mts +124 -0
  130. package/src/others/cast-mutable.mts +113 -0
  131. package/src/others/cast-readonly.mts +192 -0
  132. package/src/others/cast-readonly.test.mts +89 -0
  133. package/src/others/if-then.mts +98 -0
  134. package/src/others/if-then.test.mts +75 -0
  135. package/src/others/index.mts +7 -0
  136. package/src/others/map-nullable.mts +172 -0
  137. package/src/others/map-nullable.test.mts +297 -0
  138. package/src/others/memoize-function.mts +196 -0
  139. package/src/others/memoize-function.test.mts +168 -0
  140. package/src/others/tuple.mts +160 -0
  141. package/src/others/tuple.test.mts +11 -0
  142. package/src/others/unknown-to-string.mts +215 -0
  143. package/src/others/unknown-to-string.test.mts +114 -0
@@ -0,0 +1,177 @@
1
+ import { expectType } from '../../expect-type.mjs';
2
+ import { asNonZeroInt, isNonZeroInt, NonZeroInt } from './non-zero-int.mjs';
3
+
4
+ describe('NonZeroInt', () => {
5
+ describe('asNonZeroInt', () => {
6
+ test('accepts valid non-zero integers', () => {
7
+ expect(() => asNonZeroInt(1)).not.toThrow();
8
+ expect(() => asNonZeroInt(-1)).not.toThrow();
9
+ expect(() => asNonZeroInt(42)).not.toThrow();
10
+ expect(() => asNonZeroInt(-42)).not.toThrow();
11
+ expect(() => asNonZeroInt(Number.MAX_SAFE_INTEGER)).not.toThrow();
12
+ expect(() => asNonZeroInt(Number.MIN_SAFE_INTEGER)).not.toThrow();
13
+ });
14
+
15
+ test('rejects zero', () => {
16
+ expect(() => asNonZeroInt(0)).toThrow(TypeError);
17
+ expect(() => asNonZeroInt(-0)).toThrow(TypeError);
18
+ });
19
+
20
+ test('rejects non-integers', () => {
21
+ expect(() => asNonZeroInt(Number.NaN)).toThrow(TypeError);
22
+ expect(() => asNonZeroInt(Number.POSITIVE_INFINITY)).toThrow(TypeError);
23
+ expect(() => asNonZeroInt(Number.NEGATIVE_INFINITY)).toThrow(TypeError);
24
+ expect(() => asNonZeroInt(1.2)).toThrow(TypeError);
25
+ expect(() => asNonZeroInt(-3.4)).toThrow(TypeError);
26
+ });
27
+
28
+ test('returns the same value for valid inputs', () => {
29
+ expect(asNonZeroInt(5)).toBe(5);
30
+ expect(asNonZeroInt(-10)).toBe(-10);
31
+ expect(asNonZeroInt(1)).toBe(1);
32
+ });
33
+
34
+ test.each([
35
+ { name: 'Number.NaN', value: Number.NaN },
36
+ { name: 'Number.POSITIVE_INFINITY', value: Number.POSITIVE_INFINITY },
37
+ { name: 'Number.NEGATIVE_INFINITY', value: Number.NEGATIVE_INFINITY },
38
+ { name: '1.2', value: 1.2 },
39
+ { name: '-3.4', value: -3.4 },
40
+ { name: '0', value: 0 },
41
+ ] as const)(`asNonZeroInt($name) should throw a TypeError`, ({ value }) => {
42
+ expect(() => asNonZeroInt(value)).toThrow(
43
+ new TypeError(`Expected a non-zero integer, got: ${value}`),
44
+ );
45
+ });
46
+ });
47
+
48
+ describe('isNonZeroInt', () => {
49
+ test('correctly identifies non-zero integers', () => {
50
+ expect(isNonZeroInt(1)).toBe(true);
51
+ expect(isNonZeroInt(-1)).toBe(true);
52
+ expect(isNonZeroInt(42)).toBe(true);
53
+ expect(isNonZeroInt(-42)).toBe(true);
54
+ expect(isNonZeroInt(Number.MAX_SAFE_INTEGER)).toBe(true);
55
+ expect(isNonZeroInt(Number.MIN_SAFE_INTEGER)).toBe(true);
56
+ });
57
+
58
+ test('correctly identifies zero', () => {
59
+ expect(isNonZeroInt(0)).toBe(false);
60
+ expect(isNonZeroInt(-0)).toBe(false);
61
+ });
62
+
63
+ test('correctly identifies non-integers', () => {
64
+ expect(isNonZeroInt(Number.NaN)).toBe(false);
65
+ expect(isNonZeroInt(Number.POSITIVE_INFINITY)).toBe(false);
66
+ expect(isNonZeroInt(Number.NEGATIVE_INFINITY)).toBe(false);
67
+ expect(isNonZeroInt(1.2)).toBe(false);
68
+ expect(isNonZeroInt(-3.4)).toBe(false);
69
+ });
70
+ });
71
+
72
+ describe('NonZeroInt.is', () => {
73
+ test('same as isNonZeroInt function', () => {
74
+ expect(NonZeroInt.is(5)).toBe(isNonZeroInt(5));
75
+ expect(NonZeroInt.is(0)).toBe(isNonZeroInt(0));
76
+ expect(NonZeroInt.is(-10)).toBe(isNonZeroInt(-10));
77
+ });
78
+ });
79
+
80
+ describe('mathematical operations', () => {
81
+ const a = asNonZeroInt(5);
82
+ const b = asNonZeroInt(2);
83
+ const c = asNonZeroInt(-3);
84
+
85
+ test('abs', () => {
86
+ expect(NonZeroInt.abs(a)).toBe(5);
87
+ expect(NonZeroInt.abs(c)).toBe(3);
88
+ expect(NonZeroInt.abs(asNonZeroInt(-1))).toBe(1);
89
+ });
90
+
91
+ test('min and max', () => {
92
+ expect(NonZeroInt.min(a, b)).toBe(2);
93
+ expect(NonZeroInt.max(a, b)).toBe(5);
94
+ expect(NonZeroInt.min(a, c)).toBe(-3);
95
+ expect(NonZeroInt.max(a, c)).toBe(5);
96
+ });
97
+
98
+ test('add', () => {
99
+ expect(NonZeroInt.add(a, b)).toBe(7);
100
+ expect(NonZeroInt.add(a, c)).toBe(2);
101
+ });
102
+
103
+ test('sub', () => {
104
+ expect(NonZeroInt.sub(a, b)).toBe(3);
105
+ expect(NonZeroInt.sub(a, c)).toBe(8);
106
+ });
107
+
108
+ test('mul', () => {
109
+ expect(NonZeroInt.mul(a, b)).toBe(10);
110
+ expect(NonZeroInt.mul(a, c)).toBe(-15);
111
+ });
112
+
113
+ test('div (floor division)', () => {
114
+ expect(NonZeroInt.div(a, b)).toBe(2);
115
+ expect(NonZeroInt.div(asNonZeroInt(7), asNonZeroInt(3))).toBe(2);
116
+ expect(NonZeroInt.div(asNonZeroInt(-7), asNonZeroInt(3))).toBe(-3);
117
+ });
118
+
119
+ test('pow', () => {
120
+ expect(NonZeroInt.pow(asNonZeroInt(2), asNonZeroInt(3))).toBe(8);
121
+ expect(NonZeroInt.pow(asNonZeroInt(3), asNonZeroInt(2))).toBe(9);
122
+ expect(NonZeroInt.pow(asNonZeroInt(-2), asNonZeroInt(3))).toBe(-8);
123
+ });
124
+ });
125
+
126
+ describe('random', () => {
127
+ test('generates non-zero integers within specified range (positive range)', () => {
128
+ const min = 1;
129
+ const max = 10;
130
+
131
+ for (let i = 0; i < 10; i++) {
132
+ const result = NonZeroInt.random(min, max);
133
+ expect(result).toBeGreaterThanOrEqual(min);
134
+ expect(result).toBeLessThanOrEqual(max);
135
+ expect(NonZeroInt.is(result)).toBe(true);
136
+ expect(Number.isInteger(result)).toBe(true);
137
+ expect(result).not.toBe(0);
138
+ }
139
+ });
140
+
141
+ test('generates non-zero integers within specified range (negative range)', () => {
142
+ const min = -10;
143
+ const max = -1;
144
+
145
+ for (let i = 0; i < 10; i++) {
146
+ const result = NonZeroInt.random(min, max);
147
+ expect(result).toBeGreaterThanOrEqual(min);
148
+ expect(result).toBeLessThanOrEqual(max);
149
+ expect(NonZeroInt.is(result)).toBe(true);
150
+ expect(Number.isInteger(result)).toBe(true);
151
+ expect(result).not.toBe(0);
152
+ }
153
+ });
154
+
155
+ test('generates non-zero integers within range that spans zero', () => {
156
+ const min = -5;
157
+ const max = 5;
158
+
159
+ for (let i = 0; i < 10; i++) {
160
+ const result = NonZeroInt.random(min, max);
161
+ expect(result).toBeGreaterThanOrEqual(min);
162
+ expect(result).toBeLessThanOrEqual(max);
163
+ expect(NonZeroInt.is(result)).toBe(true);
164
+ expect(Number.isInteger(result)).toBe(true);
165
+ expect(result).not.toBe(0);
166
+ }
167
+ });
168
+ });
169
+
170
+ describe('type assertions', () => {
171
+ test('type relationships', () => {
172
+ expectType<NonZeroInt, number>('<=');
173
+
174
+ expectTypeOf(asNonZeroInt(5)).toExtend<NonZeroInt>();
175
+ });
176
+ });
177
+ });
@@ -0,0 +1,196 @@
1
+ import { expectType } from '../../expect-type.mjs';
2
+ import { TsVerifiedInternals } from '../refined-number-utils.mjs';
3
+
4
+ type ElementType = NonZeroInt16;
5
+
6
+ const typeNameInMessage = 'a non-zero integer in [-2^15, 2^15)';
7
+
8
+ const {
9
+ MIN_VALUE,
10
+ MAX_VALUE,
11
+ abs,
12
+ min: min_,
13
+ max: max_,
14
+ pow,
15
+ add,
16
+ sub,
17
+ mul,
18
+ div,
19
+ randomNonZero: random,
20
+ is,
21
+ castType,
22
+ clamp,
23
+ } = TsVerifiedInternals.RefinedNumberUtils.operatorsForInteger<
24
+ ElementType,
25
+ number,
26
+ number
27
+ >({
28
+ integerOrSafeInteger: 'SafeInteger',
29
+ nonZero: true,
30
+ MIN_VALUE: -(2 ** 15),
31
+ MAX_VALUE: 2 ** 15 - 1,
32
+ typeNameInMessage,
33
+ } as const);
34
+
35
+ /**
36
+ * Checks if a number is a NonZeroInt16 (16-bit non-zero signed integer in the range [-2^15, 2^15) excluding 0).
37
+ * @param value The value to check.
38
+ * @returns `true` if the value is a NonZeroInt16, `false` otherwise.
39
+ */
40
+ export const isNonZeroInt16 = is;
41
+
42
+ /**
43
+ * Casts a number to a NonZeroInt16 type.
44
+ * @param value The value to cast.
45
+ * @returns The value as a NonZeroInt16 type.
46
+ * @throws {TypeError} If the value is not a non-zero integer in [-2^15, 2^15).
47
+ * @example
48
+ * ```typescript
49
+ * const x = asNonZeroInt16(1000); // NonZeroInt16
50
+ * const y = asNonZeroInt16(-1000); // NonZeroInt16
51
+ * // asNonZeroInt16(0); // throws TypeError
52
+ * // asNonZeroInt16(32768); // throws TypeError
53
+ * ```
54
+ */
55
+ export const asNonZeroInt16 = castType;
56
+
57
+ /**
58
+ * Namespace providing type-safe arithmetic operations for 16-bit non-zero signed integers.
59
+ *
60
+ * All operations automatically clamp results to the valid NonZeroInt16 range [-32768, 32767]
61
+ * excluding 0. This ensures that all arithmetic maintains the 16-bit non-zero signed integer
62
+ * constraint, preventing zero results and overflow.
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const a = asNonZeroInt16(30000);
67
+ * const b = asNonZeroInt16(-10000);
68
+ *
69
+ * // Arithmetic operations with automatic clamping and non-zero constraint
70
+ * const sum = NonZeroInt16.add(a, b); // NonZeroInt16 (20000)
71
+ * const diff = NonZeroInt16.sub(a, b); // NonZeroInt16 (32767 - clamped to MAX_VALUE)
72
+ * const product = NonZeroInt16.mul(a, b); // NonZeroInt16 (-32768 - clamped to MIN_VALUE)
73
+ *
74
+ * // Utility operations
75
+ * const absolute = NonZeroInt16.abs(b); // NonZeroInt16 (10000)
76
+ * const minimum = NonZeroInt16.min(a, b); // NonZeroInt16 (-10000)
77
+ * const maximum = NonZeroInt16.max(a, b); // NonZeroInt16 (30000)
78
+ *
79
+ * // Range operations (avoiding zero)
80
+ * const clamped = NonZeroInt16.clamp(0); // NonZeroInt16 (1 or -1, avoiding zero)
81
+ * const random = NonZeroInt16.random(); // NonZeroInt16 (random non-zero value in range)
82
+ * const power = NonZeroInt16.pow(asNonZeroInt16(2), asNonZeroInt16(10)); // NonZeroInt16 (1024)
83
+ * ```
84
+ */
85
+ export const NonZeroInt16 = {
86
+ /**
87
+ * Type guard to check if a value is a NonZeroInt16.
88
+ * @param value The value to check.
89
+ * @returns `true` if the value is a 16-bit non-zero signed integer, `false` otherwise.
90
+ */
91
+ is,
92
+
93
+ /**
94
+ * The minimum value for a 16-bit non-zero signed integer.
95
+ * @readonly
96
+ */
97
+ MIN_VALUE,
98
+
99
+ /**
100
+ * The maximum value for a 16-bit non-zero signed integer.
101
+ * @readonly
102
+ */
103
+ MAX_VALUE,
104
+
105
+ /**
106
+ * Returns the absolute value of a 16-bit non-zero signed integer.
107
+ * @param a The NonZeroInt16 value.
108
+ * @returns The absolute value as a NonZeroInt16, clamped to valid range.
109
+ */
110
+ abs,
111
+
112
+ /**
113
+ * Returns the smaller of two NonZeroInt16 values.
114
+ * @param a The first NonZeroInt16.
115
+ * @param b The second NonZeroInt16.
116
+ * @returns The minimum value as a NonZeroInt16.
117
+ */
118
+ min: min_,
119
+
120
+ /**
121
+ * Returns the larger of two NonZeroInt16 values.
122
+ * @param a The first NonZeroInt16.
123
+ * @param b The second NonZeroInt16.
124
+ * @returns The maximum value as a NonZeroInt16.
125
+ */
126
+ max: max_,
127
+
128
+ /**
129
+ * Clamps a number to the NonZeroInt16 range (avoiding zero).
130
+ * @param value The number to clamp.
131
+ * @returns The value clamped to [-32768, 32767] \ {0} as a NonZeroInt16.
132
+ */
133
+ clamp,
134
+
135
+ /**
136
+ * Generates a random NonZeroInt16 value within the valid range.
137
+ * @returns A random NonZeroInt16 between MIN_VALUE and MAX_VALUE (excluding 0).
138
+ */
139
+ random,
140
+
141
+ /**
142
+ * Raises a NonZeroInt16 to the power of another NonZeroInt16.
143
+ * @param a The base NonZeroInt16.
144
+ * @param b The exponent NonZeroInt16.
145
+ * @returns `a ** b` clamped to [-32768, 32767] as a NonZeroInt16.
146
+ */
147
+ pow,
148
+
149
+ /**
150
+ * Adds two NonZeroInt16 values.
151
+ * @param a The first NonZeroInt16.
152
+ * @param b The second NonZeroInt16.
153
+ * @returns `a + b` clamped to [-32768, 32767] as a NonZeroInt16.
154
+ */
155
+ add,
156
+
157
+ /**
158
+ * Subtracts one NonZeroInt16 from another.
159
+ * @param a The minuend NonZeroInt16.
160
+ * @param b The subtrahend NonZeroInt16.
161
+ * @returns `a - b` clamped to [-32768, 32767] as a NonZeroInt16.
162
+ */
163
+ sub,
164
+
165
+ /**
166
+ * Multiplies two NonZeroInt16 values.
167
+ * @param a The first NonZeroInt16.
168
+ * @param b The second NonZeroInt16.
169
+ * @returns `a * b` clamped to [-32768, 32767] as a NonZeroInt16.
170
+ */
171
+ mul,
172
+
173
+ /**
174
+ * Divides one NonZeroInt16 by another using floor division.
175
+ * @param a The dividend NonZeroInt16.
176
+ * @param b The divisor NonZeroInt16.
177
+ * @returns `⌊a / b⌋` clamped to [-32768, 32767] as a NonZeroInt16.
178
+ */
179
+ div,
180
+ } as const;
181
+
182
+ expectType<
183
+ keyof typeof NonZeroInt16,
184
+ keyof TsVerifiedInternals.RefinedNumberUtils.NumberClass<
185
+ ElementType,
186
+ 'int' | 'range'
187
+ >
188
+ >('=');
189
+
190
+ expectType<
191
+ typeof NonZeroInt16,
192
+ TsVerifiedInternals.RefinedNumberUtils.NumberClass<
193
+ ElementType,
194
+ 'int' | 'range'
195
+ >
196
+ >('<=');
@@ -0,0 +1,195 @@
1
+ import { expectType } from '../../expect-type.mjs';
2
+ import {
3
+ asNonZeroInt16,
4
+ isNonZeroInt16,
5
+ NonZeroInt16,
6
+ } from './non-zero-int16.mjs';
7
+
8
+ describe('NonZeroInt16', () => {
9
+ describe('asNonZeroInt16', () => {
10
+ test('accepts valid non-zero int16 values', () => {
11
+ expect(() => asNonZeroInt16(1)).not.toThrow();
12
+ expect(() => asNonZeroInt16(-1)).not.toThrow();
13
+ expect(() => asNonZeroInt16(32767)).not.toThrow(); // 2^15 - 1
14
+ expect(() => asNonZeroInt16(-32768)).not.toThrow(); // -2^15
15
+ });
16
+
17
+ test('rejects zero', () => {
18
+ expect(() => asNonZeroInt16(0)).toThrow(TypeError);
19
+ });
20
+
21
+ test('rejects values outside int16 range', () => {
22
+ expect(() => asNonZeroInt16(32768)).toThrow(TypeError); // 2^15
23
+ expect(() => asNonZeroInt16(-32769)).toThrow(TypeError); // -2^15 - 1
24
+ expect(() => asNonZeroInt16(65536)).toThrow(TypeError);
25
+ expect(() => asNonZeroInt16(-65536)).toThrow(TypeError);
26
+ });
27
+
28
+ test('rejects non-integers', () => {
29
+ expect(() => asNonZeroInt16(Number.NaN)).toThrow(TypeError);
30
+ expect(() => asNonZeroInt16(Number.POSITIVE_INFINITY)).toThrow(TypeError);
31
+ expect(() => asNonZeroInt16(Number.NEGATIVE_INFINITY)).toThrow(TypeError);
32
+ expect(() => asNonZeroInt16(1.2)).toThrow(TypeError);
33
+ expect(() => asNonZeroInt16(-3.4)).toThrow(TypeError);
34
+ });
35
+
36
+ test('returns the same value for valid inputs', () => {
37
+ expect(asNonZeroInt16(5)).toBe(5);
38
+ expect(asNonZeroInt16(-10)).toBe(-10);
39
+ expect(asNonZeroInt16(32767)).toBe(32767);
40
+ expect(asNonZeroInt16(-32768)).toBe(-32768);
41
+ });
42
+
43
+ test.each([
44
+ { name: 'Number.NaN', value: Number.NaN },
45
+ { name: 'Number.POSITIVE_INFINITY', value: Number.POSITIVE_INFINITY },
46
+ { name: 'Number.NEGATIVE_INFINITY', value: Number.NEGATIVE_INFINITY },
47
+ { name: '1.2', value: 1.2 },
48
+ { name: '-3.4', value: -3.4 },
49
+ { name: '0', value: 0 },
50
+ { name: '32768', value: 32768 },
51
+ { name: '-32769', value: -32769 },
52
+ ] as const)(
53
+ `asNonZeroInt16($name) should throw a TypeError`,
54
+ ({ value }) => {
55
+ expect(() => asNonZeroInt16(value)).toThrow(
56
+ new TypeError(
57
+ `Expected a non-zero integer in [-2^15, 2^15), got: ${value}`,
58
+ ),
59
+ );
60
+ },
61
+ );
62
+ });
63
+
64
+ describe('isNonZeroInt16', () => {
65
+ test('correctly identifies non-zero int16 values', () => {
66
+ expect(isNonZeroInt16(1)).toBe(true);
67
+ expect(isNonZeroInt16(-1)).toBe(true);
68
+ expect(isNonZeroInt16(32767)).toBe(true);
69
+ expect(isNonZeroInt16(-32768)).toBe(true);
70
+ });
71
+
72
+ test('correctly identifies zero', () => {
73
+ expect(isNonZeroInt16(0)).toBe(false);
74
+ });
75
+
76
+ test('correctly identifies values outside int16 range', () => {
77
+ expect(isNonZeroInt16(32768)).toBe(false);
78
+ expect(isNonZeroInt16(-32769)).toBe(false);
79
+ expect(isNonZeroInt16(65536)).toBe(false);
80
+ expect(isNonZeroInt16(-65536)).toBe(false);
81
+ });
82
+
83
+ test('correctly identifies non-integers', () => {
84
+ expect(isNonZeroInt16(Number.NaN)).toBe(false);
85
+ expect(isNonZeroInt16(Number.POSITIVE_INFINITY)).toBe(false);
86
+ expect(isNonZeroInt16(Number.NEGATIVE_INFINITY)).toBe(false);
87
+ expect(isNonZeroInt16(1.2)).toBe(false);
88
+ expect(isNonZeroInt16(-3.4)).toBe(false);
89
+ });
90
+ });
91
+
92
+ describe('NonZeroInt16.is', () => {
93
+ test('same as isNonZeroInt16 function', () => {
94
+ expect(NonZeroInt16.is(5)).toBe(isNonZeroInt16(5));
95
+ expect(NonZeroInt16.is(0)).toBe(isNonZeroInt16(0));
96
+ expect(NonZeroInt16.is(-1)).toBe(isNonZeroInt16(-1));
97
+ });
98
+ });
99
+
100
+ describe('constants', () => {
101
+ test('MIN_VALUE and MAX_VALUE', () => {
102
+ expect(NonZeroInt16.MIN_VALUE).toBe(-32768);
103
+ expect(NonZeroInt16.MAX_VALUE).toBe(32767);
104
+ });
105
+ });
106
+
107
+ describe('mathematical operations', () => {
108
+ const a = asNonZeroInt16(100);
109
+ const b = asNonZeroInt16(50);
110
+ const c = asNonZeroInt16(-30);
111
+
112
+ test('abs', () => {
113
+ expect(NonZeroInt16.abs(a)).toBe(100);
114
+ expect(NonZeroInt16.abs(c)).toBe(30);
115
+ });
116
+
117
+ test('min and max', () => {
118
+ expect(NonZeroInt16.min(a, b)).toBe(50);
119
+ expect(NonZeroInt16.max(a, b)).toBe(100);
120
+ expect(NonZeroInt16.min(a, c)).toBe(-30);
121
+ expect(NonZeroInt16.max(a, c)).toBe(100);
122
+ });
123
+
124
+ test('add (with clamping)', () => {
125
+ const result = NonZeroInt16.add(
126
+ asNonZeroInt16(32000),
127
+ asNonZeroInt16(1000),
128
+ );
129
+ expect(result).toBe(32767); // clamped to max
130
+ expect(NonZeroInt16.add(a, b)).toBe(150);
131
+ });
132
+
133
+ test('sub (with clamping)', () => {
134
+ const result = NonZeroInt16.sub(
135
+ asNonZeroInt16(-32000),
136
+ asNonZeroInt16(1000),
137
+ );
138
+ expect(result).toBe(-32768); // clamped to min
139
+ expect(NonZeroInt16.sub(a, b)).toBe(50);
140
+ });
141
+
142
+ test('mul (with clamping)', () => {
143
+ const result = NonZeroInt16.mul(
144
+ asNonZeroInt16(1000),
145
+ asNonZeroInt16(100),
146
+ );
147
+ expect(result).toBe(32767); // clamped to max
148
+ expect(NonZeroInt16.mul(asNonZeroInt16(10), asNonZeroInt16(5))).toBe(50);
149
+ });
150
+
151
+ test('div (floor division with clamping)', () => {
152
+ expect(NonZeroInt16.div(a, asNonZeroInt16(50))).toBe(2);
153
+ expect(NonZeroInt16.div(asNonZeroInt16(7), asNonZeroInt16(3))).toBe(2);
154
+ expect(NonZeroInt16.div(asNonZeroInt16(-7), asNonZeroInt16(3))).toBe(-3);
155
+ });
156
+
157
+ test('pow (with clamping)', () => {
158
+ const result = NonZeroInt16.pow(asNonZeroInt16(200), asNonZeroInt16(3));
159
+ expect(result).toBe(32767); // clamped to max
160
+ expect(NonZeroInt16.pow(asNonZeroInt16(2), asNonZeroInt16(3))).toBe(8);
161
+ });
162
+ });
163
+
164
+ describe('random', () => {
165
+ test('generates non-zero int16 values within specified range', () => {
166
+ const min = -10;
167
+ const max = 10;
168
+
169
+ for (let i = 0; i < 10; i++) {
170
+ const result = NonZeroInt16.random(min, max);
171
+ expect(result).toBeGreaterThanOrEqual(min);
172
+ expect(result).toBeLessThanOrEqual(max);
173
+ expect(NonZeroInt16.is(result)).toBe(true);
174
+ expect(Number.isInteger(result)).toBe(true);
175
+ expect(result).not.toBe(0);
176
+ }
177
+ });
178
+
179
+ test('generates values within NonZeroInt16 range', () => {
180
+ for (let i = 0; i < 10; i++) {
181
+ const result = NonZeroInt16.random(-20, 20);
182
+ expect(result).toBeGreaterThanOrEqual(-32768);
183
+ expect(result).toBeLessThanOrEqual(32767);
184
+ }
185
+ });
186
+ });
187
+
188
+ describe('type assertions', () => {
189
+ test('type relationships', () => {
190
+ expectType<NonZeroInt16, number>('<=');
191
+
192
+ expectTypeOf(asNonZeroInt16(100)).toExtend<NonZeroInt16>();
193
+ });
194
+ });
195
+ });