ts-data-forge 4.1.0 → 5.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/array/impl/array-utils-element-access.mjs +1 -0
- package/dist/array/impl/array-utils-element-access.mjs.map +1 -1
- package/dist/array/impl/array-utils-modification.mjs +1 -0
- package/dist/array/impl/array-utils-modification.mjs.map +1 -1
- package/dist/array/impl/array-utils-reducing-value.d.mts.map +1 -1
- package/dist/array/impl/array-utils-reducing-value.mjs +2 -1
- package/dist/array/impl/array-utils-reducing-value.mjs.map +1 -1
- package/dist/array/impl/array-utils-search.mjs +1 -0
- package/dist/array/impl/array-utils-search.mjs.map +1 -1
- package/dist/array/impl/array-utils-transformation.mjs +1 -0
- package/dist/array/impl/array-utils-transformation.mjs.map +1 -1
- package/dist/collections/imap-mapped.mjs +1 -0
- package/dist/collections/imap-mapped.mjs.map +1 -1
- package/dist/collections/imap.mjs +1 -0
- package/dist/collections/imap.mjs.map +1 -1
- package/dist/collections/queue.mjs +1 -0
- package/dist/collections/queue.mjs.map +1 -1
- package/dist/collections/stack.mjs +1 -0
- package/dist/collections/stack.mjs.map +1 -1
- package/dist/functional/result/impl/result-from-throwable.d.mts.map +1 -1
- package/dist/functional/result/impl/result-from-throwable.mjs +2 -1
- package/dist/functional/result/impl/result-from-throwable.mjs.map +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-from-throwable.d.mts.map +1 -1
- package/dist/functional/ternary-result/impl/ternary-result-from-throwable.mjs +2 -1
- package/dist/functional/ternary-result/impl/ternary-result-from-throwable.mjs.map +1 -1
- package/dist/json/json.d.mts +9 -3
- package/dist/json/json.d.mts.map +1 -1
- package/dist/json/json.mjs +7 -0
- package/dist/json/json.mjs.map +1 -1
- package/dist/number/refined-number-utils.mjs +1 -0
- package/dist/number/refined-number-utils.mjs.map +1 -1
- package/dist/others/unknown-to-string.d.mts.map +1 -1
- package/dist/others/unknown-to-string.mjs +2 -1
- package/dist/others/unknown-to-string.mjs.map +1 -1
- package/dist/promise/promise.mjs +1 -0
- package/dist/promise/promise.mjs.map +1 -1
- package/package.json +18 -18
- package/src/array/impl/array-utils-creation.test.mts +187 -74
- package/src/array/impl/array-utils-element-access.test.mts +19 -3
- package/src/array/impl/array-utils-iterators.test.mts +44 -24
- package/src/array/impl/array-utils-modification.test.mts +36 -33
- package/src/array/impl/array-utils-reducing-value.mts +2 -1
- package/src/array/impl/array-utils-reducing-value.test.mts +47 -16
- package/src/array/impl/array-utils-search.test.mts +42 -9
- package/src/array/impl/array-utils-set-op.test.mts +54 -26
- package/src/array/impl/array-utils-size.test.mts +1 -0
- package/src/array/impl/array-utils-slice-clamped.test.mts +20 -11
- package/src/array/impl/array-utils-slicing.test.mts +27 -21
- package/src/array/impl/array-utils-transformation.test.mts +140 -92
- package/src/array/impl/array-utils-validation.test.mts +58 -10
- package/src/array/impl/array.test.mts +5 -5
- package/src/collections/imap-mapped.test.mts +63 -18
- package/src/collections/imap.test.mts +74 -26
- package/src/collections/iset-mapped.test.mts +81 -30
- package/src/collections/iset.test.mts +168 -68
- package/src/collections/queue.test.mts +32 -1
- package/src/collections/stack.test.mts +22 -8
- package/src/functional/match.test.mts +1 -1
- package/src/functional/optional.test.mts +61 -4
- package/src/functional/pipe.test.mts +10 -1
- package/src/functional/result/impl/result-from-throwable.mts +2 -1
- package/src/functional/result.test.mts +127 -4
- package/src/functional/ternary-result/impl/ternary-result-from-throwable.mts +2 -1
- package/src/functional/ternary-result.test.mts +34 -18
- package/src/guard/is-non-empty-string.test.mts +5 -2
- package/src/guard/is-non-null-object.test.mts +3 -5
- package/src/guard/is-primitive.test.mts +5 -3
- package/src/guard/is-record.test.mts +1 -1
- package/src/guard/is-type.test.mts +35 -20
- package/src/guard/key-is-in.test.mts +1 -1
- package/src/iterator/range.test.mts +22 -16
- package/src/json/json.mts +9 -3
- package/src/json/json.test.mts +140 -64
- package/src/number/branded-types/finite-number.test.mts +3 -2
- package/src/number/branded-types/int.test.mts +4 -3
- package/src/number/branded-types/int16.test.mts +9 -3
- package/src/number/branded-types/int32.test.mts +9 -3
- package/src/number/branded-types/non-negative-finite-number.test.mts +6 -4
- package/src/number/branded-types/non-negative-int16.test.mts +8 -3
- package/src/number/branded-types/non-negative-int32.test.mts +8 -3
- package/src/number/branded-types/non-zero-finite-number.test.mts +6 -3
- package/src/number/branded-types/non-zero-int.test.mts +6 -3
- package/src/number/branded-types/non-zero-int16.test.mts +9 -3
- package/src/number/branded-types/non-zero-int32.test.mts +9 -3
- package/src/number/branded-types/non-zero-safe-int.test.mts +10 -3
- package/src/number/branded-types/non-zero-uint16.test.mts +8 -3
- package/src/number/branded-types/non-zero-uint32.test.mts +8 -3
- package/src/number/branded-types/positive-finite-number.test.mts +7 -3
- package/src/number/branded-types/positive-int.test.mts +5 -3
- package/src/number/branded-types/positive-int16.test.mts +8 -3
- package/src/number/branded-types/positive-int32.test.mts +8 -3
- package/src/number/branded-types/positive-safe-int.test.mts +8 -3
- package/src/number/branded-types/positive-uint16.test.mts +8 -3
- package/src/number/branded-types/positive-uint32.test.mts +8 -3
- package/src/number/branded-types/safe-int.test.mts +8 -2
- package/src/number/branded-types/safe-uint.test.mts +8 -3
- package/src/number/branded-types/uint.test.mts +5 -3
- package/src/number/branded-types/uint16.test.mts +8 -3
- package/src/number/branded-types/uint32.test.mts +8 -3
- package/src/number/enum/int8.test.mts +8 -3
- package/src/number/enum/uint8.test.mts +6 -3
- package/src/number/num.test.mts +16 -2
- package/src/object/object.test.mts +26 -13
- package/src/others/cast-mutable.test.mts +10 -8
- package/src/others/cast-readonly.test.mts +9 -5
- package/src/others/if-then.test.mts +4 -1
- package/src/others/map-nullable.test.mts +28 -1
- package/src/others/memoize-function.test.mts +20 -17
- package/src/others/tuple.test.mts +3 -2
- package/src/others/unknown-to-string.mts +2 -1
- package/src/others/unknown-to-string.test.mts +15 -2
- package/src/promise/promise.test.mts +6 -1
|
@@ -4,16 +4,18 @@ import { range } from '../iterator/index.mjs';
|
|
|
4
4
|
import { asUint32 } from '../number/index.mjs';
|
|
5
5
|
import { createQueue, type Queue } from './queue.mjs';
|
|
6
6
|
|
|
7
|
-
describe('Queue', () => {
|
|
7
|
+
describe('Queue test', () => {
|
|
8
8
|
describe('initialization', () => {
|
|
9
9
|
test('should be empty if initialized without values', () => {
|
|
10
10
|
const q = createQueue();
|
|
11
|
+
|
|
11
12
|
expect(q.isEmpty).toBe(true);
|
|
12
13
|
expect(q.size).toBe(0);
|
|
13
14
|
});
|
|
14
15
|
|
|
15
16
|
test('should not be empty if initialized with values', () => {
|
|
16
17
|
const q = createQueue([1, 2, 3]);
|
|
18
|
+
|
|
17
19
|
expect(q.isEmpty).toBe(false);
|
|
18
20
|
expect(q.size).toBe(3);
|
|
19
21
|
});
|
|
@@ -29,6 +31,7 @@ describe('Queue', () => {
|
|
|
29
31
|
|
|
30
32
|
test('should increase size and not be empty after enqueueing to an empty queue', () => {
|
|
31
33
|
mut_q.enqueue(1);
|
|
34
|
+
|
|
32
35
|
expect(mut_q.isEmpty).toBe(false);
|
|
33
36
|
expect(mut_q.size).toBe(1);
|
|
34
37
|
});
|
|
@@ -36,6 +39,7 @@ describe('Queue', () => {
|
|
|
36
39
|
test('should increase size when enqueueing to a non-empty queue', () => {
|
|
37
40
|
mut_q.enqueue(1);
|
|
38
41
|
mut_q.enqueue(2);
|
|
42
|
+
|
|
39
43
|
expect(mut_q.size).toBe(2);
|
|
40
44
|
});
|
|
41
45
|
});
|
|
@@ -44,6 +48,7 @@ describe('Queue', () => {
|
|
|
44
48
|
test('should return Optional.none and size should be 0 when dequeuing from an empty queue', () => {
|
|
45
49
|
const q = createQueue<number>();
|
|
46
50
|
const result = q.dequeue();
|
|
51
|
+
|
|
47
52
|
expect(Optional.isNone(result)).toBe(true);
|
|
48
53
|
expect(q.isEmpty).toBe(true);
|
|
49
54
|
expect(q.size).toBe(0);
|
|
@@ -54,17 +59,23 @@ describe('Queue', () => {
|
|
|
54
59
|
const initialSize = q.size;
|
|
55
60
|
|
|
56
61
|
const result1 = q.dequeue(); // Dequeues 1 (first element)
|
|
62
|
+
|
|
57
63
|
expect(Optional.isSome(result1)).toBe(true);
|
|
64
|
+
|
|
58
65
|
if (Optional.isSome(result1)) {
|
|
59
66
|
expect(result1.value).toBe(1);
|
|
60
67
|
}
|
|
68
|
+
|
|
61
69
|
expect(q.size).toBe(initialSize - 1);
|
|
62
70
|
|
|
63
71
|
const result2 = q.dequeue(); // Dequeues 2
|
|
72
|
+
|
|
64
73
|
expect(Optional.isSome(result2)).toBe(true);
|
|
74
|
+
|
|
65
75
|
if (Optional.isSome(result2)) {
|
|
66
76
|
expect(result2.value).toBe(2);
|
|
67
77
|
}
|
|
78
|
+
|
|
68
79
|
expect(q.size).toBe(initialSize - 2);
|
|
69
80
|
});
|
|
70
81
|
|
|
@@ -72,9 +83,12 @@ describe('Queue', () => {
|
|
|
72
83
|
const q = createQueue([1, 2]); // Internal: [1, 2]
|
|
73
84
|
q.dequeue(); // Dequeues 1
|
|
74
85
|
q.dequeue(); // Dequeues 2
|
|
86
|
+
|
|
75
87
|
expect(q.isEmpty).toBe(true);
|
|
76
88
|
expect(q.size).toBe(0);
|
|
89
|
+
|
|
77
90
|
const result = q.dequeue(); // Dequeue from empty
|
|
91
|
+
|
|
78
92
|
expect(Optional.isNone(result)).toBe(true);
|
|
79
93
|
});
|
|
80
94
|
});
|
|
@@ -89,33 +103,41 @@ describe('Queue', () => {
|
|
|
89
103
|
expect(q.size).toBe(3);
|
|
90
104
|
|
|
91
105
|
let mut_result = q.dequeue(); // Dequeues 1 (first in)
|
|
106
|
+
|
|
92
107
|
expect(Optional.isSome(mut_result) && mut_result.value === 1).toBe(true);
|
|
93
108
|
expect(q.size).toBe(2);
|
|
94
109
|
|
|
95
110
|
mut_result = q.dequeue(); // Dequeues 2
|
|
111
|
+
|
|
96
112
|
expect(Optional.isSome(mut_result) && mut_result.value === 2).toBe(true);
|
|
97
113
|
expect(q.size).toBe(1);
|
|
98
114
|
|
|
99
115
|
mut_result = q.dequeue(); // Dequeues 3
|
|
116
|
+
|
|
100
117
|
expect(Optional.isSome(mut_result) && mut_result.value === 3).toBe(true);
|
|
101
118
|
expect(q.size).toBe(0);
|
|
102
119
|
expect(q.isEmpty).toBe(true);
|
|
103
120
|
|
|
104
121
|
mut_result = q.dequeue();
|
|
122
|
+
|
|
105
123
|
expect(Optional.isNone(mut_result)).toBe(true);
|
|
106
124
|
});
|
|
107
125
|
|
|
108
126
|
test('initial values are dequeued in the same order (FIFO)', () => {
|
|
109
127
|
const q = createQueue([1, 2, 3]); // Internal: [1, 2, 3]
|
|
128
|
+
|
|
110
129
|
expect(q.size).toBe(3);
|
|
111
130
|
|
|
112
131
|
const result1 = q.dequeue(); // Dequeues 1 (first element)
|
|
132
|
+
|
|
113
133
|
expect(Optional.isSome(result1) && result1.value === 1).toBe(true);
|
|
114
134
|
|
|
115
135
|
const result2 = q.dequeue(); // Dequeues 2
|
|
136
|
+
|
|
116
137
|
expect(Optional.isSome(result2) && result2.value === 2).toBe(true);
|
|
117
138
|
|
|
118
139
|
const result3 = q.dequeue(); // Dequeues 3
|
|
140
|
+
|
|
119
141
|
expect(Optional.isSome(result3) && result3.value === 3).toBe(true);
|
|
120
142
|
|
|
121
143
|
expect(q.isEmpty).toBe(true);
|
|
@@ -128,18 +150,22 @@ describe('Queue', () => {
|
|
|
128
150
|
q.enqueue('B');
|
|
129
151
|
|
|
130
152
|
const result1 = q.dequeue();
|
|
153
|
+
|
|
131
154
|
expect(Optional.isSome(result1) && result1.value === 'A').toBe(true);
|
|
132
155
|
|
|
133
156
|
q.enqueue('C');
|
|
134
157
|
q.enqueue('D');
|
|
135
158
|
|
|
136
159
|
const result2 = q.dequeue();
|
|
160
|
+
|
|
137
161
|
expect(Optional.isSome(result2) && result2.value === 'B').toBe(true);
|
|
138
162
|
|
|
139
163
|
const result3 = q.dequeue();
|
|
164
|
+
|
|
140
165
|
expect(Optional.isSome(result3) && result3.value === 'C').toBe(true);
|
|
141
166
|
|
|
142
167
|
const result4 = q.dequeue();
|
|
168
|
+
|
|
143
169
|
expect(Optional.isSome(result4) && result4.value === 'D').toBe(true);
|
|
144
170
|
|
|
145
171
|
expect(q.isEmpty).toBe(true);
|
|
@@ -188,6 +214,7 @@ describe('Queue', () => {
|
|
|
188
214
|
// Verify all elements can be dequeued in correct order
|
|
189
215
|
for (const i of range(1, 21)) {
|
|
190
216
|
const result = q.dequeue();
|
|
217
|
+
|
|
191
218
|
expect(Optional.isSome(result) && result.value === i).toBe(true);
|
|
192
219
|
}
|
|
193
220
|
|
|
@@ -233,9 +260,11 @@ describe('Queue', () => {
|
|
|
233
260
|
// Test single element enqueue/dequeue cycles
|
|
234
261
|
for (const i of range(10)) {
|
|
235
262
|
q.enqueue(`item-${i}`);
|
|
263
|
+
|
|
236
264
|
expect(q.size).toBe(1);
|
|
237
265
|
|
|
238
266
|
const result = q.dequeue();
|
|
267
|
+
|
|
239
268
|
expect(Optional.isSome(result) && result.value === `item-${i}`).toBe(
|
|
240
269
|
true,
|
|
241
270
|
);
|
|
@@ -269,12 +298,14 @@ describe('Queue', () => {
|
|
|
269
298
|
// Remove first 5 objects
|
|
270
299
|
for (const i of range(0, 5)) {
|
|
271
300
|
const result = q.dequeue();
|
|
301
|
+
|
|
272
302
|
expect(Optional.isSome(result) && result.value.id === i).toBe(true);
|
|
273
303
|
}
|
|
274
304
|
|
|
275
305
|
// Remaining objects should still be accessible
|
|
276
306
|
for (const i of range(5, 10)) {
|
|
277
307
|
const result = q.dequeue();
|
|
308
|
+
|
|
278
309
|
expect(Optional.isSome(result) && result.value.id === i).toBe(true);
|
|
279
310
|
}
|
|
280
311
|
|
|
@@ -4,7 +4,7 @@ import { range } from '../iterator/index.mjs';
|
|
|
4
4
|
import { asPositiveSafeInt, asSafeInt } from '../number/index.mjs';
|
|
5
5
|
import { createStack, type Stack } from './stack.mjs';
|
|
6
6
|
|
|
7
|
-
describe('Stack', () => {
|
|
7
|
+
describe('Stack test', () => {
|
|
8
8
|
test('should have correct type definitions', () => {
|
|
9
9
|
const stack = createStack<number>();
|
|
10
10
|
|
|
@@ -15,10 +15,10 @@ describe('Stack', () => {
|
|
|
15
15
|
expectType<typeof stack.push, (value: number) => void>('=');
|
|
16
16
|
|
|
17
17
|
// Verify the type checking works at runtime too
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
expectTypeOf(stack.isEmpty).toBeBoolean();
|
|
19
|
+
expectTypeOf(stack.size).toBeNumber();
|
|
20
|
+
expectTypeOf(stack.pop).toBeFunction();
|
|
21
|
+
expectTypeOf(stack.push).toBeFunction();
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
test('should be empty when created without initial values', () => {
|
|
@@ -66,6 +66,7 @@ describe('Stack', () => {
|
|
|
66
66
|
const stack = createStack<number>();
|
|
67
67
|
|
|
68
68
|
const result = stack.pop();
|
|
69
|
+
|
|
69
70
|
expect(Optional.isNone(result)).toBe(true);
|
|
70
71
|
expect(stack.isEmpty).toBe(true);
|
|
71
72
|
expect(stack.size).toBe(0);
|
|
@@ -77,21 +78,27 @@ describe('Stack', () => {
|
|
|
77
78
|
expect(stack.size).toBe(0);
|
|
78
79
|
|
|
79
80
|
stack.push(1);
|
|
81
|
+
|
|
80
82
|
expect(stack.size).toBe(1);
|
|
81
83
|
|
|
82
84
|
stack.push(2);
|
|
85
|
+
|
|
83
86
|
expect(stack.size).toBe(2);
|
|
84
87
|
|
|
85
88
|
stack.push(3);
|
|
89
|
+
|
|
86
90
|
expect(stack.size).toBe(3);
|
|
87
91
|
|
|
88
92
|
Optional.unwrap(stack.pop());
|
|
93
|
+
|
|
89
94
|
expect(stack.size).toBe(2);
|
|
90
95
|
|
|
91
96
|
Optional.unwrap(stack.pop());
|
|
97
|
+
|
|
92
98
|
expect(stack.size).toBe(1);
|
|
93
99
|
|
|
94
100
|
Optional.unwrap(stack.pop());
|
|
101
|
+
|
|
95
102
|
expect(stack.size).toBe(0);
|
|
96
103
|
expect(stack.isEmpty).toBe(true);
|
|
97
104
|
});
|
|
@@ -102,11 +109,13 @@ describe('Stack', () => {
|
|
|
102
109
|
stack.push('a');
|
|
103
110
|
// eslint-disable-next-line unicorn/prefer-single-call
|
|
104
111
|
stack.push('b');
|
|
112
|
+
|
|
105
113
|
expect(Optional.unwrap(stack.pop())).toBe('b');
|
|
106
114
|
|
|
107
115
|
stack.push('c');
|
|
108
116
|
// eslint-disable-next-line unicorn/prefer-single-call
|
|
109
117
|
stack.push('d');
|
|
118
|
+
|
|
110
119
|
expect(Optional.unwrap(stack.pop())).toBe('d');
|
|
111
120
|
expect(Optional.unwrap(stack.pop())).toBe('c');
|
|
112
121
|
expect(Optional.unwrap(stack.pop())).toBe('a');
|
|
@@ -125,8 +134,9 @@ describe('Stack', () => {
|
|
|
125
134
|
// eslint-disable-next-line unicorn/prefer-single-call
|
|
126
135
|
stack.push(item2);
|
|
127
136
|
|
|
128
|
-
|
|
129
|
-
|
|
137
|
+
assert.deepStrictEqual(Optional.unwrap(stack.pop()), item2);
|
|
138
|
+
assert.deepStrictEqual(Optional.unwrap(stack.pop()), item1);
|
|
139
|
+
|
|
130
140
|
expect(stack.isEmpty).toBe(true);
|
|
131
141
|
});
|
|
132
142
|
|
|
@@ -145,6 +155,7 @@ describe('Stack', () => {
|
|
|
145
155
|
// Pop all elements and verify LIFO order
|
|
146
156
|
for (const i of range(asSafeInt(n - 1), -1, -1)) {
|
|
147
157
|
const result = stack.pop();
|
|
158
|
+
|
|
148
159
|
expect(Optional.isSome(result)).toBe(true);
|
|
149
160
|
expect(Optional.unwrap(result)).toBe(i);
|
|
150
161
|
}
|
|
@@ -165,7 +176,8 @@ describe('Stack', () => {
|
|
|
165
176
|
|
|
166
177
|
// Original array should be unchanged
|
|
167
178
|
expect(initialValues).toHaveLength(originalLength);
|
|
168
|
-
|
|
179
|
+
|
|
180
|
+
assert.deepStrictEqual(initialValues, [1, 2, 3]);
|
|
169
181
|
});
|
|
170
182
|
|
|
171
183
|
test('should work with undefined and null values', () => {
|
|
@@ -217,6 +229,7 @@ describe('Stack', () => {
|
|
|
217
229
|
if (i % 2 === 1) {
|
|
218
230
|
// Pop every other time
|
|
219
231
|
const result = stack.pop();
|
|
232
|
+
|
|
220
233
|
expect(Optional.unwrap(result)).toBe(i);
|
|
221
234
|
}
|
|
222
235
|
}
|
|
@@ -227,6 +240,7 @@ describe('Stack', () => {
|
|
|
227
240
|
// Verify elements are in correct LIFO order
|
|
228
241
|
for (const i of range(98, -1, -2)) {
|
|
229
242
|
const result = stack.pop();
|
|
243
|
+
|
|
230
244
|
expect(Optional.unwrap(result)).toBe(i);
|
|
231
245
|
}
|
|
232
246
|
|
|
@@ -2,7 +2,7 @@ import { expectType } from '../expect-type.mjs';
|
|
|
2
2
|
import { Optional } from './optional/index.mjs';
|
|
3
3
|
import { pipe } from './pipe.mjs';
|
|
4
4
|
|
|
5
|
-
describe('Optional', () => {
|
|
5
|
+
describe('Optional test', () => {
|
|
6
6
|
describe('isOptional', () => {
|
|
7
7
|
test('should return true for Some values', () => {
|
|
8
8
|
expect(Optional.isOptional(Optional.some(42))).toBe(true);
|
|
@@ -28,16 +28,20 @@ describe('Optional', () => {
|
|
|
28
28
|
describe('some', () => {
|
|
29
29
|
test('should create a Some variant with the provided value', () => {
|
|
30
30
|
const someNumber = Optional.some(42);
|
|
31
|
+
|
|
31
32
|
expect(Optional.isSome(someNumber)).toBe(true);
|
|
32
33
|
expect(Optional.unwrap(someNumber)).toBe(42);
|
|
33
34
|
|
|
34
35
|
const someString = Optional.some('hello');
|
|
36
|
+
|
|
35
37
|
expect(Optional.isSome(someString)).toBe(true);
|
|
36
38
|
expect(Optional.unwrap(someString)).toBe('hello');
|
|
37
39
|
|
|
38
40
|
const someObject = Optional.some({ name: 'Alice', age: 30 });
|
|
41
|
+
|
|
39
42
|
expect(Optional.isSome(someObject)).toBe(true);
|
|
40
|
-
|
|
43
|
+
|
|
44
|
+
assert.deepStrictEqual(Optional.unwrap(someObject), {
|
|
41
45
|
name: 'Alice',
|
|
42
46
|
age: 30,
|
|
43
47
|
});
|
|
@@ -66,12 +70,14 @@ describe('Optional', () => {
|
|
|
66
70
|
describe('isSome and isNone', () => {
|
|
67
71
|
test('should correctly identify Some values', () => {
|
|
68
72
|
const some = Optional.some(42);
|
|
73
|
+
|
|
69
74
|
expect(Optional.isSome(some)).toBe(true);
|
|
70
75
|
expect(Optional.isNone(some)).toBe(false);
|
|
71
76
|
});
|
|
72
77
|
|
|
73
78
|
test('should correctly identify None values', () => {
|
|
74
79
|
const none = Optional.none;
|
|
80
|
+
|
|
75
81
|
expect(Optional.isSome(none)).toBe(false);
|
|
76
82
|
expect(Optional.isNone(none)).toBe(true);
|
|
77
83
|
});
|
|
@@ -95,6 +101,7 @@ describe('Optional', () => {
|
|
|
95
101
|
const mapped = Optional.map(some, (x) => x * 2);
|
|
96
102
|
|
|
97
103
|
expect(Optional.isSome(mapped)).toBe(true);
|
|
104
|
+
|
|
98
105
|
if (Optional.isSome(mapped)) {
|
|
99
106
|
expect(Optional.unwrap(mapped)).toBe(10);
|
|
100
107
|
}
|
|
@@ -120,6 +127,7 @@ describe('Optional', () => {
|
|
|
120
127
|
|
|
121
128
|
test('should preserve types correctly', () => {
|
|
122
129
|
const some = Optional.some(42);
|
|
130
|
+
|
|
123
131
|
expectTypeOf(Optional.map(some, (x) => x.toString())).toEqualTypeOf<
|
|
124
132
|
Optional<string>
|
|
125
133
|
>();
|
|
@@ -132,12 +140,14 @@ describe('Optional', () => {
|
|
|
132
140
|
const mapped = doubler(some);
|
|
133
141
|
|
|
134
142
|
expect(Optional.isSome(mapped)).toBe(true);
|
|
143
|
+
|
|
135
144
|
if (Optional.isSome(mapped)) {
|
|
136
145
|
expect(Optional.unwrap(mapped)).toBe(10);
|
|
137
146
|
}
|
|
138
147
|
|
|
139
148
|
const none = Optional.none;
|
|
140
149
|
const mappedNone = doubler(none);
|
|
150
|
+
|
|
141
151
|
expect(Optional.isNone(mappedNone)).toBe(true);
|
|
142
152
|
});
|
|
143
153
|
|
|
@@ -148,6 +158,7 @@ describe('Optional', () => {
|
|
|
148
158
|
const result = pipe(Optional.some(5)).map(doubler).map(toStringFn).value;
|
|
149
159
|
|
|
150
160
|
expect(Optional.isSome(result)).toBe(true);
|
|
161
|
+
|
|
151
162
|
if (Optional.isSome(result)) {
|
|
152
163
|
expect(Optional.unwrap(result)).toBe('10');
|
|
153
164
|
}
|
|
@@ -168,9 +179,11 @@ describe('Optional', () => {
|
|
|
168
179
|
|
|
169
180
|
test('should have correct return types', () => {
|
|
170
181
|
const someNumber = Optional.some(42);
|
|
182
|
+
|
|
171
183
|
expectTypeOf(Optional.unwrap(someNumber)).toExtend<number | undefined>();
|
|
172
184
|
|
|
173
185
|
const none = Optional.none;
|
|
186
|
+
|
|
174
187
|
// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
|
|
175
188
|
expectTypeOf(Optional.unwrapOr(none, undefined)).toExtend<undefined>();
|
|
176
189
|
});
|
|
@@ -190,6 +203,7 @@ describe('Optional', () => {
|
|
|
190
203
|
|
|
191
204
|
test('should have correct return types', () => {
|
|
192
205
|
const someNumber = Optional.some(42);
|
|
206
|
+
|
|
193
207
|
expectTypeOf(Optional.unwrapThrow(someNumber)).toExtend<number>();
|
|
194
208
|
});
|
|
195
209
|
});
|
|
@@ -209,6 +223,7 @@ describe('Optional', () => {
|
|
|
209
223
|
|
|
210
224
|
test('should have correct return types', () => {
|
|
211
225
|
const someNumber = Optional.some(42);
|
|
226
|
+
|
|
212
227
|
expectTypeOf(Optional.unwrapOr(someNumber, 0)).toExtend<number>();
|
|
213
228
|
|
|
214
229
|
expectTypeOf(Optional.unwrapOr(someNumber, 'default')).toExtend<
|
|
@@ -216,6 +231,7 @@ describe('Optional', () => {
|
|
|
216
231
|
>();
|
|
217
232
|
|
|
218
233
|
const none = Optional.none;
|
|
234
|
+
|
|
219
235
|
expectTypeOf(Optional.unwrapOr(none, 'default')).toExtend<string>();
|
|
220
236
|
});
|
|
221
237
|
|
|
@@ -224,10 +240,12 @@ describe('Optional', () => {
|
|
|
224
240
|
|
|
225
241
|
const someValue = Optional.some(100);
|
|
226
242
|
const result = unwrapWithDefault(someValue);
|
|
243
|
+
|
|
227
244
|
expect(result).toBe(100);
|
|
228
245
|
|
|
229
246
|
const noneValue = Optional.none;
|
|
230
247
|
const defaultResult = unwrapWithDefault(noneValue);
|
|
248
|
+
|
|
231
249
|
expect(defaultResult).toBe(42);
|
|
232
250
|
});
|
|
233
251
|
|
|
@@ -237,9 +255,11 @@ describe('Optional', () => {
|
|
|
237
255
|
const someResult = pipe(Optional.some('hello')).map(
|
|
238
256
|
unwrapWithDefault,
|
|
239
257
|
).value;
|
|
258
|
+
|
|
240
259
|
expect(someResult).toBe('hello');
|
|
241
260
|
|
|
242
261
|
const noneResult = pipe(Optional.none).map(unwrapWithDefault).value;
|
|
262
|
+
|
|
243
263
|
expect(noneResult).toBe('default');
|
|
244
264
|
});
|
|
245
265
|
});
|
|
@@ -247,11 +267,13 @@ describe('Optional', () => {
|
|
|
247
267
|
describe('expectToBe', () => {
|
|
248
268
|
test('should return the value for Some', () => {
|
|
249
269
|
const expectNumber = Optional.expectToBe<number>('Expected a number');
|
|
270
|
+
|
|
250
271
|
expect(expectNumber(Optional.some(42))).toBe(42);
|
|
251
272
|
});
|
|
252
273
|
|
|
253
274
|
test('should throw with custom message for None', () => {
|
|
254
275
|
const expectNumber = Optional.expectToBe<number>('Expected a number');
|
|
276
|
+
|
|
255
277
|
expect(() => expectNumber(Optional.none)).toThrow('Expected a number');
|
|
256
278
|
});
|
|
257
279
|
|
|
@@ -270,9 +292,11 @@ describe('Optional', () => {
|
|
|
270
292
|
|
|
271
293
|
const someValue = Optional.some('important data');
|
|
272
294
|
const result = getValue(someValue);
|
|
295
|
+
|
|
273
296
|
expect(result).toBe('important data');
|
|
274
297
|
|
|
275
298
|
const noneValue = Optional.none;
|
|
299
|
+
|
|
276
300
|
expect(() => getValue(noneValue)).toThrow('Value must exist');
|
|
277
301
|
});
|
|
278
302
|
|
|
@@ -282,7 +306,8 @@ describe('Optional', () => {
|
|
|
282
306
|
const someResult = pipe(Optional.some({ name: 'Alice', age: 30 })).map(
|
|
283
307
|
expectUser,
|
|
284
308
|
).value;
|
|
285
|
-
|
|
309
|
+
|
|
310
|
+
assert.deepStrictEqual(someResult, { name: 'Alice', age: 30 });
|
|
286
311
|
|
|
287
312
|
expect(() => pipe(Optional.none).map(expectUser).value).toThrow(
|
|
288
313
|
'User not found',
|
|
@@ -324,6 +349,7 @@ describe('Optional', () => {
|
|
|
324
349
|
}
|
|
325
350
|
|
|
326
351
|
const invalid = Optional.flatMap(Optional.some('abc'), parseNumber);
|
|
352
|
+
|
|
327
353
|
expect(Optional.isNone(invalid)).toBe(true);
|
|
328
354
|
});
|
|
329
355
|
|
|
@@ -331,6 +357,7 @@ describe('Optional', () => {
|
|
|
331
357
|
const result = Optional.flatMap(Optional.none, (_: never) =>
|
|
332
358
|
Optional.some(42),
|
|
333
359
|
);
|
|
360
|
+
|
|
334
361
|
expect(Optional.isNone(result)).toBe(true);
|
|
335
362
|
});
|
|
336
363
|
|
|
@@ -364,15 +391,19 @@ describe('Optional', () => {
|
|
|
364
391
|
const parser = Optional.flatMap(parseNumber);
|
|
365
392
|
|
|
366
393
|
const result = parser(Optional.some('42'));
|
|
394
|
+
|
|
367
395
|
expect(Optional.isSome(result)).toBe(true);
|
|
396
|
+
|
|
368
397
|
if (Optional.isSome(result)) {
|
|
369
398
|
expect(Optional.unwrap(result)).toBe(42);
|
|
370
399
|
}
|
|
371
400
|
|
|
372
401
|
const invalid = parser(Optional.some('abc'));
|
|
402
|
+
|
|
373
403
|
expect(Optional.isNone(invalid)).toBe(true);
|
|
374
404
|
|
|
375
405
|
const noneResult = parser(Optional.none);
|
|
406
|
+
|
|
376
407
|
expect(Optional.isNone(noneResult)).toBe(true);
|
|
377
408
|
});
|
|
378
409
|
|
|
@@ -391,6 +422,7 @@ describe('Optional', () => {
|
|
|
391
422
|
const result = pipe(Optional.some('42')).map(parser).map(doubler).value;
|
|
392
423
|
|
|
393
424
|
expect(Optional.isSome(result)).toBe(true);
|
|
425
|
+
|
|
394
426
|
if (Optional.isSome(result)) {
|
|
395
427
|
expect(Optional.unwrap(result)).toBe(84);
|
|
396
428
|
}
|
|
@@ -409,11 +441,13 @@ describe('Optional', () => {
|
|
|
409
441
|
test('should return None for Some values that do not match predicate', () => {
|
|
410
442
|
const someOdd = Optional.some(5);
|
|
411
443
|
const filtered = Optional.filter(someOdd, (x) => x % 2 === 0);
|
|
444
|
+
|
|
412
445
|
expect(Optional.isNone(filtered)).toBe(true);
|
|
413
446
|
});
|
|
414
447
|
|
|
415
448
|
test('should return None if input is None', () => {
|
|
416
449
|
const filtered = Optional.filter(Optional.none, (_: never) => true);
|
|
450
|
+
|
|
417
451
|
expect(Optional.isNone(filtered)).toBe(true);
|
|
418
452
|
});
|
|
419
453
|
|
|
@@ -422,16 +456,20 @@ describe('Optional', () => {
|
|
|
422
456
|
|
|
423
457
|
const someEven = Optional.some(4);
|
|
424
458
|
const filtered = evenFilter(someEven);
|
|
459
|
+
|
|
425
460
|
expect(Optional.isSome(filtered)).toBe(true);
|
|
461
|
+
|
|
426
462
|
if (Optional.isSome(filtered)) {
|
|
427
463
|
expect(Optional.unwrap(filtered)).toBe(4);
|
|
428
464
|
}
|
|
429
465
|
|
|
430
466
|
const someOdd = Optional.some(5);
|
|
431
467
|
const filteredOdd = evenFilter(someOdd);
|
|
468
|
+
|
|
432
469
|
expect(Optional.isNone(filteredOdd)).toBe(true);
|
|
433
470
|
|
|
434
471
|
const noneResult = evenFilter(Optional.none);
|
|
472
|
+
|
|
435
473
|
expect(Optional.isNone(noneResult)).toBe(true);
|
|
436
474
|
});
|
|
437
475
|
|
|
@@ -444,6 +482,7 @@ describe('Optional', () => {
|
|
|
444
482
|
.map(positiveFilter).value;
|
|
445
483
|
|
|
446
484
|
expect(Optional.isSome(result)).toBe(true);
|
|
485
|
+
|
|
447
486
|
if (Optional.isSome(result)) {
|
|
448
487
|
expect(Optional.unwrap(result)).toBe(4);
|
|
449
488
|
}
|
|
@@ -475,6 +514,7 @@ describe('Optional', () => {
|
|
|
475
514
|
|
|
476
515
|
test('should return None if both are None', () => {
|
|
477
516
|
const result = Optional.orElse(Optional.none, Optional.none);
|
|
517
|
+
|
|
478
518
|
expect(Optional.isNone(result)).toBe(true);
|
|
479
519
|
});
|
|
480
520
|
|
|
@@ -483,14 +523,18 @@ describe('Optional', () => {
|
|
|
483
523
|
|
|
484
524
|
const someValue = Optional.some('primary');
|
|
485
525
|
const result = fallbackTo(someValue);
|
|
526
|
+
|
|
486
527
|
expect(Optional.isSome(result)).toBe(true);
|
|
528
|
+
|
|
487
529
|
if (Optional.isSome(result)) {
|
|
488
530
|
expect(Optional.unwrap(result)).toBe('primary');
|
|
489
531
|
}
|
|
490
532
|
|
|
491
533
|
const noneValue = Optional.none;
|
|
492
534
|
const fallbackResult = fallbackTo(noneValue);
|
|
535
|
+
|
|
493
536
|
expect(Optional.isSome(fallbackResult)).toBe(true);
|
|
537
|
+
|
|
494
538
|
if (Optional.isSome(fallbackResult)) {
|
|
495
539
|
expect(Optional.unwrap(fallbackResult)).toBe('fallback');
|
|
496
540
|
}
|
|
@@ -500,13 +544,17 @@ describe('Optional', () => {
|
|
|
500
544
|
const fallbackTo = Optional.orElse(Optional.some('backup'));
|
|
501
545
|
|
|
502
546
|
const someResult = pipe(Optional.some('original')).map(fallbackTo).value;
|
|
547
|
+
|
|
503
548
|
expect(Optional.isSome(someResult)).toBe(true);
|
|
549
|
+
|
|
504
550
|
if (Optional.isSome(someResult)) {
|
|
505
551
|
expect(Optional.unwrap(someResult)).toBe('original');
|
|
506
552
|
}
|
|
507
553
|
|
|
508
554
|
const noneResult = pipe(Optional.none).map(fallbackTo).value;
|
|
555
|
+
|
|
509
556
|
expect(Optional.isSome(noneResult)).toBe(true);
|
|
557
|
+
|
|
510
558
|
if (Optional.isSome(noneResult)) {
|
|
511
559
|
expect(Optional.unwrap(noneResult)).toBe('backup');
|
|
512
560
|
}
|
|
@@ -519,7 +567,7 @@ describe('Optional', () => {
|
|
|
519
567
|
const b = Optional.some('hello');
|
|
520
568
|
const zipped = Optional.zip(a, b);
|
|
521
569
|
if (Optional.isSome(zipped)) {
|
|
522
|
-
|
|
570
|
+
assert.deepStrictEqual(Optional.unwrap(zipped), [1, 'hello']);
|
|
523
571
|
}
|
|
524
572
|
});
|
|
525
573
|
|
|
@@ -527,6 +575,7 @@ describe('Optional', () => {
|
|
|
527
575
|
const a = Optional.none;
|
|
528
576
|
const b = Optional.some('hello');
|
|
529
577
|
const zipped = Optional.zip(a, b);
|
|
578
|
+
|
|
530
579
|
expect(Optional.isNone(zipped)).toBe(true);
|
|
531
580
|
});
|
|
532
581
|
|
|
@@ -534,11 +583,13 @@ describe('Optional', () => {
|
|
|
534
583
|
const a = Optional.some(1);
|
|
535
584
|
const b = Optional.none;
|
|
536
585
|
const zipped = Optional.zip(a, b);
|
|
586
|
+
|
|
537
587
|
expect(Optional.isNone(zipped)).toBe(true);
|
|
538
588
|
});
|
|
539
589
|
|
|
540
590
|
test('should return None if both are None', () => {
|
|
541
591
|
const zipped = Optional.zip(Optional.none, Optional.none);
|
|
592
|
+
|
|
542
593
|
expect(Optional.isNone(zipped)).toBe(true);
|
|
543
594
|
});
|
|
544
595
|
});
|
|
@@ -573,6 +624,7 @@ describe('Optional', () => {
|
|
|
573
624
|
|
|
574
625
|
test('should work with union types', () => {
|
|
575
626
|
const value: string | null = 'test';
|
|
627
|
+
|
|
576
628
|
expectTypeOf(Optional.fromNullable(value)).toExtend<Optional<string>>();
|
|
577
629
|
});
|
|
578
630
|
});
|
|
@@ -591,6 +643,7 @@ describe('Optional', () => {
|
|
|
591
643
|
|
|
592
644
|
test('should have correct return type', () => {
|
|
593
645
|
const some = Optional.some(42);
|
|
646
|
+
|
|
594
647
|
expectTypeOf(Optional.toNullable(some)).toExtend<number | undefined>();
|
|
595
648
|
});
|
|
596
649
|
});
|
|
@@ -598,6 +651,7 @@ describe('Optional', () => {
|
|
|
598
651
|
describe('edge cases', () => {
|
|
599
652
|
test('should handle undefined as a Some value', () => {
|
|
600
653
|
const someUndefined = Optional.some(undefined);
|
|
654
|
+
|
|
601
655
|
expect(Optional.isSome(someUndefined)).toBe(true);
|
|
602
656
|
// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
|
|
603
657
|
expect(Optional.unwrap(someUndefined)).toBeUndefined();
|
|
@@ -608,15 +662,18 @@ describe('Optional', () => {
|
|
|
608
662
|
|
|
609
663
|
test('should handle null as a Some value', () => {
|
|
610
664
|
const someNull = Optional.some(null);
|
|
665
|
+
|
|
611
666
|
expect(Optional.isSome(someNull)).toBe(true);
|
|
612
667
|
expect(Optional.unwrap(someNull)).toBeNull();
|
|
613
668
|
});
|
|
614
669
|
|
|
615
670
|
test('should handle nested Optionals', () => {
|
|
616
671
|
const nested = Optional.some(Optional.some(42));
|
|
672
|
+
|
|
617
673
|
expect(Optional.isSome(nested)).toBe(true);
|
|
618
674
|
|
|
619
675
|
const inner = Optional.unwrap(nested);
|
|
676
|
+
|
|
620
677
|
expect(Optional.isOptional(inner)).toBe(true);
|
|
621
678
|
expect(Optional.unwrap(inner)).toBe(42);
|
|
622
679
|
});
|