ts-data-forge 4.1.0 → 5.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 (76) hide show
  1. package/dist/json/json.d.mts +9 -3
  2. package/dist/json/json.d.mts.map +1 -1
  3. package/dist/json/json.mjs +6 -0
  4. package/dist/json/json.mjs.map +1 -1
  5. package/package.json +13 -13
  6. package/src/array/impl/array-utils-creation.test.mts +187 -74
  7. package/src/array/impl/array-utils-element-access.test.mts +19 -3
  8. package/src/array/impl/array-utils-iterators.test.mts +44 -24
  9. package/src/array/impl/array-utils-modification.test.mts +36 -33
  10. package/src/array/impl/array-utils-reducing-value.test.mts +47 -16
  11. package/src/array/impl/array-utils-search.test.mts +42 -9
  12. package/src/array/impl/array-utils-set-op.test.mts +54 -26
  13. package/src/array/impl/array-utils-size.test.mts +1 -0
  14. package/src/array/impl/array-utils-slice-clamped.test.mts +20 -11
  15. package/src/array/impl/array-utils-slicing.test.mts +27 -21
  16. package/src/array/impl/array-utils-transformation.test.mts +140 -92
  17. package/src/array/impl/array-utils-validation.test.mts +58 -10
  18. package/src/array/impl/array.test.mts +5 -5
  19. package/src/collections/imap-mapped.test.mts +63 -18
  20. package/src/collections/imap.test.mts +74 -26
  21. package/src/collections/iset-mapped.test.mts +81 -30
  22. package/src/collections/iset.test.mts +168 -68
  23. package/src/collections/queue.test.mts +32 -1
  24. package/src/collections/stack.test.mts +22 -8
  25. package/src/functional/match.test.mts +1 -1
  26. package/src/functional/optional.test.mts +61 -4
  27. package/src/functional/pipe.test.mts +10 -1
  28. package/src/functional/result.test.mts +127 -4
  29. package/src/functional/ternary-result.test.mts +34 -18
  30. package/src/guard/is-non-empty-string.test.mts +5 -2
  31. package/src/guard/is-non-null-object.test.mts +3 -5
  32. package/src/guard/is-primitive.test.mts +5 -3
  33. package/src/guard/is-record.test.mts +1 -1
  34. package/src/guard/is-type.test.mts +35 -20
  35. package/src/guard/key-is-in.test.mts +1 -1
  36. package/src/iterator/range.test.mts +22 -16
  37. package/src/json/json.mts +9 -3
  38. package/src/json/json.test.mts +140 -64
  39. package/src/number/branded-types/finite-number.test.mts +3 -2
  40. package/src/number/branded-types/int.test.mts +4 -3
  41. package/src/number/branded-types/int16.test.mts +9 -3
  42. package/src/number/branded-types/int32.test.mts +9 -3
  43. package/src/number/branded-types/non-negative-finite-number.test.mts +6 -4
  44. package/src/number/branded-types/non-negative-int16.test.mts +8 -3
  45. package/src/number/branded-types/non-negative-int32.test.mts +8 -3
  46. package/src/number/branded-types/non-zero-finite-number.test.mts +6 -3
  47. package/src/number/branded-types/non-zero-int.test.mts +6 -3
  48. package/src/number/branded-types/non-zero-int16.test.mts +9 -3
  49. package/src/number/branded-types/non-zero-int32.test.mts +9 -3
  50. package/src/number/branded-types/non-zero-safe-int.test.mts +10 -3
  51. package/src/number/branded-types/non-zero-uint16.test.mts +8 -3
  52. package/src/number/branded-types/non-zero-uint32.test.mts +8 -3
  53. package/src/number/branded-types/positive-finite-number.test.mts +7 -3
  54. package/src/number/branded-types/positive-int.test.mts +5 -3
  55. package/src/number/branded-types/positive-int16.test.mts +8 -3
  56. package/src/number/branded-types/positive-int32.test.mts +8 -3
  57. package/src/number/branded-types/positive-safe-int.test.mts +8 -3
  58. package/src/number/branded-types/positive-uint16.test.mts +8 -3
  59. package/src/number/branded-types/positive-uint32.test.mts +8 -3
  60. package/src/number/branded-types/safe-int.test.mts +8 -2
  61. package/src/number/branded-types/safe-uint.test.mts +8 -3
  62. package/src/number/branded-types/uint.test.mts +5 -3
  63. package/src/number/branded-types/uint16.test.mts +8 -3
  64. package/src/number/branded-types/uint32.test.mts +8 -3
  65. package/src/number/enum/int8.test.mts +8 -3
  66. package/src/number/enum/uint8.test.mts +6 -3
  67. package/src/number/num.test.mts +16 -2
  68. package/src/object/object.test.mts +26 -13
  69. package/src/others/cast-mutable.test.mts +10 -8
  70. package/src/others/cast-readonly.test.mts +9 -5
  71. package/src/others/if-then.test.mts +4 -1
  72. package/src/others/map-nullable.test.mts +28 -1
  73. package/src/others/memoize-function.test.mts +20 -17
  74. package/src/others/tuple.test.mts +3 -2
  75. package/src/others/unknown-to-string.test.mts +15 -2
  76. package/src/promise/promise.test.mts +6 -1
@@ -2,7 +2,7 @@ import { expectType } from '../expect-type.mjs';
2
2
  import { Optional } from './optional/index.mjs';
3
3
  import { TernaryResult } from './ternary-result/index.mjs';
4
4
 
5
- describe('TernaryResult', () => {
5
+ describe('TernaryResult test', () => {
6
6
  test('constructors and guards', () => {
7
7
  const ok = TernaryResult.ok(1);
8
8
  const warn = TernaryResult.warn(1, 'caution');
@@ -64,10 +64,12 @@ describe('TernaryResult', () => {
64
64
 
65
65
  expect(TernaryResult.unwrapOk(okResult)).toBe(3);
66
66
  expect(TernaryResult.isWarn(warnResult)).toBe(true);
67
+
67
68
  if (TernaryResult.isWarn(warnResult)) {
68
69
  expect(warnResult.value).toBe(3);
69
70
  expect(warnResult.warning).toBe('slow');
70
71
  }
72
+
71
73
  expect(TernaryResult.unwrapErr(errResult)).toBe('bad');
72
74
  });
73
75
 
@@ -93,24 +95,28 @@ describe('TernaryResult', () => {
93
95
 
94
96
  expect(TernaryResult.unwrapOk(value)).toBe(2);
95
97
  expect(TernaryResult.unwrapOk(warn)).toBe(4);
96
- expect(TernaryResult.unwrapWarn(warn)).toStrictEqual({
98
+
99
+ assert.deepStrictEqual(TernaryResult.unwrapWarn(warn), {
97
100
  warning: 'heads up',
98
101
  });
99
- expect(TernaryResult.unwrapErr(err)).toStrictEqual({ message: 'boom' });
102
+ assert.deepStrictEqual(TernaryResult.unwrapErr(err), { message: 'boom' });
100
103
  });
101
104
 
102
105
  test('orElse keeps Ok and Warn variants', () => {
103
106
  const fallback = TernaryResult.ok('fallback');
104
107
 
105
- expect(
108
+ assert.deepStrictEqual(
106
109
  TernaryResult.orElse(TernaryResult.ok('value'), fallback),
107
- ).toStrictEqual(TernaryResult.ok('value'));
108
- expect(
110
+ TernaryResult.ok('value'),
111
+ );
112
+ assert.deepStrictEqual(
109
113
  TernaryResult.orElse(TernaryResult.warn('value', 'warn'), fallback),
110
- ).toStrictEqual(TernaryResult.warn('value', 'warn'));
111
- expect(
114
+ TernaryResult.warn('value', 'warn'),
115
+ );
116
+ assert.deepStrictEqual(
112
117
  TernaryResult.orElse(TernaryResult.err('err'), fallback),
113
- ).toStrictEqual(fallback);
118
+ fallback,
119
+ );
114
120
  });
115
121
 
116
122
  test('unwrap helpers', () => {
@@ -150,26 +156,32 @@ describe('TernaryResult', () => {
150
156
  const warn = TernaryResult.warn('warn', 'warned');
151
157
  const err = TernaryResult.err('err');
152
158
 
153
- expect(TernaryResult.zip(ok, TernaryResult.ok(1))).toStrictEqual(
159
+ assert.deepStrictEqual(
160
+ TernaryResult.zip(ok, TernaryResult.ok(1)),
154
161
  TernaryResult.ok(['x', 1] as const),
155
162
  );
156
- expect(TernaryResult.zip(ok, warn)).toStrictEqual(
163
+ assert.deepStrictEqual(
164
+ TernaryResult.zip(ok, warn),
157
165
  TernaryResult.warn(['x', 'warn'] as const, 'warned'),
158
166
  );
159
- expect(TernaryResult.zip(warn, ok)).toStrictEqual(
167
+ assert.deepStrictEqual(
168
+ TernaryResult.zip(warn, ok),
160
169
  TernaryResult.warn(['warn', 'x'] as const, 'warned'),
161
170
  );
162
- expect(TernaryResult.zip(ok, err)).toStrictEqual(err);
163
- expect(TernaryResult.zip(err, warn)).toStrictEqual(err);
171
+ assert.deepStrictEqual(TernaryResult.zip(ok, err), err);
172
+ assert.deepStrictEqual(TernaryResult.zip(err, warn), err);
164
173
  });
165
174
 
166
175
  test('toOptional keeps only Ok values', () => {
167
- expect(TernaryResult.toOptional(TernaryResult.ok(1))).toStrictEqual(
176
+ assert.deepStrictEqual(
177
+ TernaryResult.toOptional(TernaryResult.ok(1)),
168
178
  Optional.some(1),
169
179
  );
170
- expect(
180
+ assert.deepStrictEqual(
171
181
  TernaryResult.toOptional(TernaryResult.warn(1, 'warn')),
172
- ).toStrictEqual(Optional.some(1));
182
+ Optional.some(1),
183
+ );
184
+
173
185
  expect(TernaryResult.toOptional(TernaryResult.err('err'))).toBe(
174
186
  Optional.none,
175
187
  );
@@ -183,16 +195,20 @@ describe('TernaryResult', () => {
183
195
  const rejected = await TernaryResult.fromPromise(
184
196
  Promise.reject(new Error('bad')),
185
197
  );
198
+
186
199
  expect(TernaryResult.isErr(rejected)).toBe(true);
187
200
  });
188
201
 
189
202
  test('fromThrowable converts thrown values', () => {
190
- expect(TernaryResult.fromThrowable(() => 5)).toStrictEqual(
203
+ assert.deepStrictEqual(
204
+ TernaryResult.fromThrowable(() => 5),
191
205
  TernaryResult.ok(5),
192
206
  );
207
+
193
208
  const errorResult = TernaryResult.fromThrowable(() => {
194
209
  throw new Error('boom');
195
210
  });
211
+
196
212
  expect(TernaryResult.isErr(errorResult)).toBe(true);
197
213
  });
198
214
  });
@@ -1,7 +1,7 @@
1
1
  import { expectType } from '../expect-type.mjs';
2
2
  import { isNonEmptyString } from './is-non-empty-string.mjs';
3
3
 
4
- describe('isNonEmptyString', () => {
4
+ describe(isNonEmptyString, () => {
5
5
  test('should return true for non-empty strings', () => {
6
6
  expect(isNonEmptyString('hello')).toBe(true);
7
7
  expect(isNonEmptyString('a')).toBe(true);
@@ -42,6 +42,7 @@ describe('isNonEmptyString', () => {
42
42
  // @ts-expect-error Testing non-string types
43
43
  if (isNonEmptyString(value)) {
44
44
  expectType<typeof value, string>('=');
45
+
45
46
  // TypeScript knows it's a string
46
47
  expect(value.length).toBeGreaterThan(0);
47
48
  expect(value.charAt(0)).toBe('t');
@@ -53,6 +54,7 @@ describe('isNonEmptyString', () => {
53
54
 
54
55
  if (isNonEmptyString(maybeString)) {
55
56
  expectType<typeof maybeString, string>('=');
57
+
56
58
  expect(maybeString.toUpperCase()).toBe('HELLO');
57
59
  }
58
60
  });
@@ -71,7 +73,8 @@ describe('isNonEmptyString', () => {
71
73
 
72
74
  // @ts-expect-error Testing non-string types
73
75
  const nonEmptyStrings = mixed.filter(isNonEmptyString);
74
- expect(nonEmptyStrings).toStrictEqual(['valid', 'another', 'third']);
76
+
77
+ assert.deepStrictEqual(nonEmptyStrings, ['valid', 'another', 'third']);
75
78
  });
76
79
 
77
80
  test('should handle string edge cases', () => {
@@ -1,7 +1,7 @@
1
1
  import { expectType } from '../expect-type.mjs';
2
2
  import { isNonNullObject } from './is-non-null-object.mjs';
3
3
 
4
- describe('isNonNullObject', () => {
4
+ describe(isNonNullObject, () => {
5
5
  test('should return true for plain objects', () => {
6
6
  expect(isNonNullObject({})).toBe(true);
7
7
  expect(isNonNullObject({ a: 1, b: 'test' })).toBe(true);
@@ -57,9 +57,7 @@ describe('isNonNullObject', () => {
57
57
  const value: unknown = { test: true };
58
58
 
59
59
  if (isNonNullObject(value)) {
60
- expectType<typeof value, NonNullable<UnknownRecord>>('>=');
61
- // Can access object methods
62
- expect(typeof value.toString).toBe('function');
60
+ expectType<typeof value, object>('=');
63
61
  }
64
62
  });
65
63
 
@@ -85,6 +83,6 @@ describe('isNonNullObject', () => {
85
83
 
86
84
  const objects = mixed.filter(isNonNullObject);
87
85
 
88
- expect(objects).toStrictEqual([{ a: 1 }, []]);
86
+ assert.deepStrictEqual(objects, [{ a: 1 }, []]);
89
87
  });
90
88
  });
@@ -1,7 +1,8 @@
1
1
  import { expectType } from '../expect-type.mjs';
2
2
  import { isPrimitive } from './is-primitive.mjs';
3
+ import { isSymbol } from './is-type.mjs';
3
4
 
4
- describe('isPrimitive', () => {
5
+ describe(isPrimitive, () => {
5
6
  test('should return true for string primitives', () => {
6
7
  expect(isPrimitive('hello')).toBe(true);
7
8
  expect(isPrimitive('')).toBe(true);
@@ -95,8 +96,9 @@ describe('isPrimitive', () => {
95
96
  expect(primitives[2]).toBe(true);
96
97
  expect(primitives[3]).toBeNull();
97
98
  expect(primitives[4]).toBeUndefined();
98
- expect(typeof primitives[5]).toBe('symbol');
99
99
 
100
- expect(nonPrimitives).toStrictEqual([{}, []]);
100
+ expect(isSymbol(primitives[5])).toBe(true);
101
+
102
+ assert.deepStrictEqual(nonPrimitives, [{}, []]);
101
103
  });
102
104
  });
@@ -1,7 +1,7 @@
1
1
  import { expectType } from '../expect-type.mjs';
2
2
  import { isRecord } from './is-record.mjs';
3
3
 
4
- describe('isRecord', () => {
4
+ describe(isRecord, () => {
5
5
  test('{ x: 1 } is a record', () => {
6
6
  const obj = { x: 1 } as const;
7
7
  const unk: unknown = obj;
@@ -18,7 +18,7 @@ import {
18
18
  isUndefined,
19
19
  } from './is-type.mjs';
20
20
 
21
- describe('isUndefined', () => {
21
+ describe(isUndefined, () => {
22
22
  test('should return true for undefined', () => {
23
23
  expect(isUndefined(undefined)).toBe(true);
24
24
  });
@@ -39,7 +39,7 @@ describe('isUndefined', () => {
39
39
  });
40
40
  });
41
41
 
42
- describe('isNotUndefined', () => {
42
+ describe(isNotUndefined, () => {
43
43
  test('should return false for undefined', () => {
44
44
  expect(isNotUndefined(undefined)).toBe(false);
45
45
  });
@@ -59,7 +59,7 @@ describe('isNotUndefined', () => {
59
59
  });
60
60
  });
61
61
 
62
- describe('isNull', () => {
62
+ describe(isNull, () => {
63
63
  test('should return true for null', () => {
64
64
  expect(isNull(null)).toBe(true);
65
65
  });
@@ -80,7 +80,7 @@ describe('isNull', () => {
80
80
  });
81
81
  });
82
82
 
83
- describe('isNotNull', () => {
83
+ describe(isNotNull, () => {
84
84
  test('should return false for null', () => {
85
85
  expect(isNotNull(null)).toBe(false);
86
86
  });
@@ -99,7 +99,7 @@ describe('isNotNull', () => {
99
99
  });
100
100
  });
101
101
 
102
- describe('isString', () => {
102
+ describe(isString, () => {
103
103
  test('should return true for strings', () => {
104
104
  expect(isString('')).toBe(true);
105
105
  expect(isString('hello')).toBe(true);
@@ -120,12 +120,13 @@ describe('isString', () => {
120
120
  const value: unknown = 'test';
121
121
  if (isString(value)) {
122
122
  expectType<typeof value, string>('=');
123
+
123
124
  expect(value).toHaveLength(4);
124
125
  }
125
126
  });
126
127
  });
127
128
 
128
- describe('isNumber', () => {
129
+ describe(isNumber, () => {
129
130
  test('should return true for numbers', () => {
130
131
  expect(isNumber(0)).toBe(true);
131
132
  expect(isNumber(42)).toBe(true);
@@ -148,12 +149,13 @@ describe('isNumber', () => {
148
149
  const value: unknown = 42;
149
150
  if (isNumber(value)) {
150
151
  expectType<typeof value, number>('=');
152
+
151
153
  expect(value + 1).toBe(43);
152
154
  }
153
155
  });
154
156
  });
155
157
 
156
- describe('isBigint', () => {
158
+ describe(isBigint, () => {
157
159
  test('should return true for bigints', () => {
158
160
  expect(isBigint(0n)).toBe(true);
159
161
  expect(isBigint(123n)).toBe(true);
@@ -171,12 +173,13 @@ describe('isBigint', () => {
171
173
  const value: unknown = 123n;
172
174
  if (isBigint(value)) {
173
175
  expectType<typeof value, bigint>('=');
176
+
174
177
  expect(value + 1n).toBe(124n);
175
178
  }
176
179
  });
177
180
  });
178
181
 
179
- describe('isBoolean', () => {
182
+ describe(isBoolean, () => {
180
183
  test('should return true for booleans', () => {
181
184
  expect(isBoolean(true)).toBe(true);
182
185
  expect(isBoolean(false)).toBe(true);
@@ -195,12 +198,13 @@ describe('isBoolean', () => {
195
198
  const value: unknown = true;
196
199
  if (isBoolean(value)) {
197
200
  expectType<typeof value, boolean>('=');
201
+
198
202
  expect(!value).toBe(false);
199
203
  }
200
204
  });
201
205
  });
202
206
 
203
- describe('isSymbol', () => {
207
+ describe(isSymbol, () => {
204
208
  test('should return true for symbols', () => {
205
209
  expect(isSymbol(Symbol())).toBe(true);
206
210
  expect(isSymbol(Symbol('test'))).toBe(true);
@@ -217,12 +221,13 @@ describe('isSymbol', () => {
217
221
  const value: unknown = Symbol('test');
218
222
  if (isSymbol(value)) {
219
223
  expectType<typeof value, symbol>('=');
224
+
220
225
  expect(value.toString()).toContain('Symbol');
221
226
  }
222
227
  });
223
228
  });
224
229
 
225
- describe('isNotBoolean', () => {
230
+ describe(isNotBoolean, () => {
226
231
  test('should return false for boolean values', () => {
227
232
  expect(isNotBoolean(true)).toBe(false);
228
233
  expect(isNotBoolean(false)).toBe(false);
@@ -243,13 +248,14 @@ describe('isNotBoolean', () => {
243
248
  const value: string | number | boolean = 'test';
244
249
  if (isNotBoolean(value)) {
245
250
  expectType<typeof value, string | number>('<=');
251
+
246
252
  // Should not have boolean methods
247
253
  expect(typeof value === 'string' || typeof value === 'number').toBe(true);
248
254
  }
249
255
  });
250
256
  });
251
257
 
252
- describe('isNotNumber', () => {
258
+ describe(isNotNumber, () => {
253
259
  test('should return false for number values', () => {
254
260
  expect(isNotNumber(0)).toBe(false);
255
261
  expect(isNotNumber(42)).toBe(false);
@@ -275,6 +281,7 @@ describe('isNotNumber', () => {
275
281
  const value: string | number | boolean = 'test';
276
282
  if (isNotNumber(value)) {
277
283
  expectType<typeof value, string | boolean>('<=');
284
+
278
285
  expect(typeof value === 'string' || typeof value === 'boolean').toBe(
279
286
  true,
280
287
  );
@@ -282,7 +289,7 @@ describe('isNotNumber', () => {
282
289
  });
283
290
  });
284
291
 
285
- describe('isNotBigint', () => {
292
+ describe(isNotBigint, () => {
286
293
  test('should return false for bigint values', () => {
287
294
  expect(isNotBigint(0n)).toBe(false);
288
295
  expect(isNotBigint(123n)).toBe(false);
@@ -304,12 +311,13 @@ describe('isNotBigint', () => {
304
311
  const value: number | bigint = 123;
305
312
  if (isNotBigint(value)) {
306
313
  expectType<typeof value, number>('<=');
307
- expect(typeof value).toBe('number');
314
+
315
+ expectTypeOf(value).toBeNumber();
308
316
  }
309
317
  });
310
318
  });
311
319
 
312
- describe('isNotString', () => {
320
+ describe(isNotString, () => {
313
321
  test('should return false for string values', () => {
314
322
  expect(isNotString('')).toBe(false);
315
323
  expect(isNotString('hello')).toBe(false);
@@ -333,6 +341,7 @@ describe('isNotString', () => {
333
341
  const value: string | number | boolean = 42;
334
342
  if (isNotString(value)) {
335
343
  expectType<typeof value, number | boolean>('<=');
344
+
336
345
  expect(typeof value === 'number' || typeof value === 'boolean').toBe(
337
346
  true,
338
347
  );
@@ -340,7 +349,7 @@ describe('isNotString', () => {
340
349
  });
341
350
  });
342
351
 
343
- describe('isNotSymbol', () => {
352
+ describe(isNotSymbol, () => {
344
353
  test('should return false for symbol values', () => {
345
354
  expect(isNotSymbol(Symbol())).toBe(false);
346
355
  expect(isNotSymbol(Symbol('test'))).toBe(false);
@@ -363,12 +372,13 @@ describe('isNotSymbol', () => {
363
372
  const value: string | number | symbol = 'test';
364
373
  if (isNotSymbol(value)) {
365
374
  expectType<typeof value, string | number>('<=');
375
+
366
376
  expect(typeof value === 'string' || typeof value === 'number').toBe(true);
367
377
  }
368
378
  });
369
379
  });
370
380
 
371
- describe('isNullish', () => {
381
+ describe(isNullish, () => {
372
382
  test('should return true for null and undefined', () => {
373
383
  expect(isNullish(null)).toBe(true);
374
384
  expect(isNullish(undefined)).toBe(true);
@@ -389,6 +399,7 @@ describe('isNullish', () => {
389
399
  const value: string | null | undefined = null;
390
400
  if (isNullish(value)) {
391
401
  expectType<typeof value, null | undefined>('<=');
402
+
392
403
  // Value is guaranteed to be null or undefined in this branch
393
404
  expect(true).toBe(true);
394
405
  }
@@ -401,7 +412,7 @@ describe('isNullish', () => {
401
412
  });
402
413
  });
403
414
 
404
- describe('isNonNullish', () => {
415
+ describe(isNonNullish, () => {
405
416
  test('should return false for null and undefined', () => {
406
417
  expect(isNonNullish(null)).toBe(false);
407
418
  expect(isNonNullish(undefined)).toBe(false);
@@ -424,6 +435,7 @@ describe('isNonNullish', () => {
424
435
  const value: string | null | undefined = 'test';
425
436
  if (isNonNullish(value)) {
426
437
  expectType<typeof value, string>('<=');
438
+
427
439
  expect(value).toHaveLength(4);
428
440
  }
429
441
  });
@@ -441,7 +453,8 @@ describe('isNonNullish', () => {
441
453
  expectType<typeof definedItems, string[]>('<=');
442
454
 
443
455
  expect(definedItems).toHaveLength(3);
444
- expect(definedItems).toStrictEqual(['hello', 'world', 'test']);
456
+
457
+ assert.deepStrictEqual(definedItems, ['hello', 'world', 'test']);
445
458
  });
446
459
 
447
460
  test('should handle complex union types', () => {
@@ -450,6 +463,7 @@ describe('isNonNullish', () => {
450
463
 
451
464
  if (isNonNullish(value)) {
452
465
  expectType<typeof value, string | number | boolean>('<=');
466
+
453
467
  // Value is guaranteed to be non-nullish in this branch
454
468
  expect(true).toBe(true);
455
469
  }
@@ -462,7 +476,8 @@ describe('type guard behavior in complex scenarios', () => {
462
476
 
463
477
  if (isNonNullish(value) && isNotBoolean(value) && isNotNumber(value)) {
464
478
  expectType<typeof value, string>('<=');
465
- expect(typeof value).toBe('string');
479
+
480
+ expectTypeOf(value).toBeString();
466
481
  }
467
482
  });
468
483
 
@@ -487,6 +502,6 @@ describe('type guard behavior in complex scenarios', () => {
487
502
  const strings = nonBooleans.filter(isNotNumber);
488
503
  expectType<typeof strings, string[]>('<=');
489
504
 
490
- expect(strings).toStrictEqual(['hello', 'world']);
505
+ assert.deepStrictEqual(strings, ['hello', 'world']);
491
506
  });
492
507
  });
@@ -5,7 +5,7 @@ const f = <Key extends string, V, KeySub extends Key>(
5
5
  obj: ReadonlyRecord<KeySub, V>,
6
6
  ): V | undefined => (keyIsIn(key, obj) ? obj[key] : undefined);
7
7
 
8
- describe('keyIsIn', () => {
8
+ describe(keyIsIn, () => {
9
9
  f('a' as 'a' | 'b' | 'c', { a: 0, b: 1 });
10
10
 
11
11
  test('', () => {
@@ -1,46 +1,52 @@
1
1
  import { range } from './range.mjs';
2
2
 
3
- describe('range', () => {
3
+ describe(range, () => {
4
4
  test('range(0, 10)', () => {
5
- expect(Array.from(range(0, 10))).toStrictEqual([
6
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
7
- ]);
5
+ assert.deepStrictEqual(
6
+ Array.from(range(0, 10)),
7
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
8
+ );
8
9
  });
9
10
 
10
11
  test('range(10)', () => {
11
- expect(Array.from(range(10))).toStrictEqual([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
12
+ assert.deepStrictEqual(
13
+ Array.from(range(10)),
14
+ [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
15
+ );
12
16
  });
13
17
 
14
18
  test('range(0)', () => {
15
- expect(Array.from(range(0))).toStrictEqual([]);
19
+ assert.deepStrictEqual(Array.from(range(0)), []);
16
20
  });
17
21
 
18
22
  test('range(-1)', () => {
19
23
  // @ts-expect-error negative end is not allowed
20
- expect(Array.from(range(-1))).toStrictEqual([]);
24
+ assert.deepStrictEqual(Array.from(range(-1)), []);
21
25
  });
22
26
 
23
27
  test('range(10, 0, -1)', () => {
24
- expect(Array.from(range(10, 0, -1))).toStrictEqual([
25
- 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
26
- ]);
28
+ assert.deepStrictEqual(
29
+ Array.from(range(10, 0, -1)),
30
+ [10, 9, 8, 7, 6, 5, 4, 3, 2, 1],
31
+ );
27
32
  });
28
33
 
29
34
  test('range(0, -10, -1)', () => {
30
- expect(Array.from(range(0, -10, -1))).toStrictEqual([
31
- 0, -1, -2, -3, -4, -5, -6, -7, -8, -9,
32
- ]);
35
+ assert.deepStrictEqual(
36
+ Array.from(range(0, -10, -1)),
37
+ [0, -1, -2, -3, -4, -5, -6, -7, -8, -9],
38
+ );
33
39
  });
34
40
 
35
41
  test('range(0, 0)', () => {
36
- expect(Array.from(range(0, 0))).toStrictEqual([]);
42
+ assert.deepStrictEqual(Array.from(range(0, 0)), []);
37
43
  });
38
44
 
39
45
  test('range(0, 11, 2)', () => {
40
- expect(Array.from(range(0, 11, 2))).toStrictEqual([0, 2, 4, 6, 8, 10]);
46
+ assert.deepStrictEqual(Array.from(range(0, 11, 2)), [0, 2, 4, 6, 8, 10]);
41
47
  });
42
48
 
43
49
  test('range(1, 12, 2)', () => {
44
- expect(Array.from(range(1, 12, 2))).toStrictEqual([1, 3, 5, 7, 9, 11]);
50
+ assert.deepStrictEqual(Array.from(range(1, 12, 2)), [1, 3, 5, 7, 9, 11]);
45
51
  });
46
52
  });
package/src/json/json.mts CHANGED
@@ -108,6 +108,8 @@ export namespace Json {
108
108
  *
109
109
  * assert.ok(Result.isOk(filtered));
110
110
  * if (Result.isOk(filtered)) {
111
+ * assert(isString(filtered.value));
112
+ *
111
113
  * assert.ok(!filtered.value.includes('age'));
112
114
  * }
113
115
  * ```
@@ -136,7 +138,7 @@ export namespace Json {
136
138
  value: unknown,
137
139
  replacer?: (this: unknown, key: string, val: unknown) => unknown,
138
140
  space?: UintRangeInclusive<1, 10> | string,
139
- ): Result<string, string> => {
141
+ ): Result<string | undefined, string> => {
140
142
  try {
141
143
  return Result.ok(JSON.stringify(value, replacer, space));
142
144
  } catch (error) {
@@ -170,6 +172,8 @@ export namespace Json {
170
172
  *
171
173
  * assert.ok(Result.isOk(safeJson));
172
174
  * if (Result.isOk(safeJson)) {
175
+ * assert(isString(safeJson.value));
176
+ *
173
177
  * const parsed: unknown = JSON.parse(safeJson.value);
174
178
  * assert.deepStrictEqual(parsed, {
175
179
  * id: 1,
@@ -207,7 +211,7 @@ export namespace Json {
207
211
  value: unknown,
208
212
  propertiesToBeSelected?: readonly (number | string)[],
209
213
  space?: UintRangeInclusive<1, 10> | string,
210
- ): Result<string, string> => {
214
+ ): Result<string | undefined, string> => {
211
215
  try {
212
216
  return Result.ok(
213
217
  JSON.stringify(value, castMutable(propertiesToBeSelected), space),
@@ -257,6 +261,8 @@ export namespace Json {
257
261
  * const formatted = Json.stringifySortedKey(unorderedData, 2);
258
262
  * assert.ok(Result.isOk(formatted));
259
263
  * if (Result.isOk(formatted)) {
264
+ * assert(isString(formatted.value));
265
+ *
260
266
  * // Check that keys are in order (first key should be "apple")
261
267
  * assert.ok(
262
268
  * formatted.value.indexOf('"apple"') < formatted.value.indexOf('"mango"'),
@@ -288,7 +294,7 @@ export namespace Json {
288
294
  export const stringifySortedKey = (
289
295
  value: UnknownRecord,
290
296
  space?: UintRangeInclusive<1, 10> | string,
291
- ): Result<string, string> => {
297
+ ): Result<string | undefined, string> => {
292
298
  const allKeys = pipe(keysDeep(value))
293
299
  .map((keys) => Arr.uniq(keys))
294
300
  .map((ks) => ks.toSorted()).value;