ts-data-forge 13.0.0 → 14.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 (72) hide show
  1. package/README.md +1 -1
  2. package/dist/array/impl/array-utils-creation.d.mts +2 -2
  3. package/dist/array/impl/array-utils-creation.d.mts.map +1 -1
  4. package/dist/array/impl/array-utils-creation.mjs.map +1 -1
  5. package/dist/array/impl/array-utils-length-bounded-array-cast.d.mts +56 -29
  6. package/dist/array/impl/array-utils-length-bounded-array-cast.d.mts.map +1 -1
  7. package/dist/array/impl/array-utils-length-bounded-array-cast.mjs +23 -15
  8. package/dist/array/impl/array-utils-length-bounded-array-cast.mjs.map +1 -1
  9. package/dist/array/impl/array-utils-length-bounded-array-guard.d.mts +126 -28
  10. package/dist/array/impl/array-utils-length-bounded-array-guard.d.mts.map +1 -1
  11. package/dist/array/impl/array-utils-length-bounded-array-guard.mjs +39 -5
  12. package/dist/array/impl/array-utils-length-bounded-array-guard.mjs.map +1 -1
  13. package/dist/array/impl/array-utils-length-bounded-tuple-cast.d.mts +167 -0
  14. package/dist/array/impl/array-utils-length-bounded-tuple-cast.d.mts.map +1 -0
  15. package/dist/array/impl/array-utils-length-bounded-tuple-cast.mjs +87 -0
  16. package/dist/array/impl/array-utils-length-bounded-tuple-cast.mjs.map +1 -0
  17. package/dist/array/impl/array-utils-length-bounded-tuple-guard.d.mts +135 -0
  18. package/dist/array/impl/array-utils-length-bounded-tuple-guard.d.mts.map +1 -0
  19. package/dist/array/impl/array-utils-length-bounded-tuple-guard.mjs +41 -0
  20. package/dist/array/impl/array-utils-length-bounded-tuple-guard.mjs.map +1 -0
  21. package/dist/array/impl/array-utils-modification.d.mts +32 -18
  22. package/dist/array/impl/array-utils-modification.d.mts.map +1 -1
  23. package/dist/array/impl/array-utils-modification.mjs.map +1 -1
  24. package/dist/array/impl/array-utils-reducing-value.d.mts +3 -3
  25. package/dist/array/impl/array-utils-reducing-value.d.mts.map +1 -1
  26. package/dist/array/impl/array-utils-reducing-value.mjs +1 -1
  27. package/dist/array/impl/array-utils-reducing-value.mjs.map +1 -1
  28. package/dist/array/impl/array-utils-slicing.d.mts +11 -11
  29. package/dist/array/impl/array-utils-slicing.d.mts.map +1 -1
  30. package/dist/array/impl/array-utils-slicing.mjs +1 -1
  31. package/dist/array/impl/array-utils-slicing.mjs.map +1 -1
  32. package/dist/array/impl/array-utils-transformation.d.mts +35 -23
  33. package/dist/array/impl/array-utils-transformation.d.mts.map +1 -1
  34. package/dist/array/impl/array-utils-transformation.mjs +2 -2
  35. package/dist/array/impl/array-utils-transformation.mjs.map +1 -1
  36. package/dist/array/impl/array-utils-validation.d.mts +2 -124
  37. package/dist/array/impl/array-utils-validation.d.mts.map +1 -1
  38. package/dist/array/impl/array-utils-validation.mjs +1 -7
  39. package/dist/array/impl/array-utils-validation.mjs.map +1 -1
  40. package/dist/array/impl/index.d.mts +2 -0
  41. package/dist/array/impl/index.d.mts.map +1 -1
  42. package/dist/array/impl/index.mjs +5 -3
  43. package/dist/array/impl/index.mjs.map +1 -1
  44. package/dist/object/object.mjs +1 -1
  45. package/dist/string/str.d.mts +44 -44
  46. package/dist/string/str.d.mts.map +1 -1
  47. package/dist/string/str.mjs +17 -17
  48. package/dist/string/str.mjs.map +1 -1
  49. package/package.json +2 -2
  50. package/src/array/impl/array-utils-creation.mts +7 -3
  51. package/src/array/impl/array-utils-length-bounded-array-cast.mts +88 -50
  52. package/src/array/impl/array-utils-length-bounded-array-cast.test.mts +40 -13
  53. package/src/array/impl/array-utils-length-bounded-array-guard.mts +248 -39
  54. package/src/array/impl/array-utils-length-bounded-array-guard.test.mts +135 -24
  55. package/src/array/impl/array-utils-length-bounded-tuple-cast.mts +364 -0
  56. package/src/array/impl/array-utils-length-bounded-tuple-cast.test.mts +207 -0
  57. package/src/array/impl/array-utils-length-bounded-tuple-guard.mts +266 -0
  58. package/src/array/impl/array-utils-length-bounded-tuple-guard.test.mts +441 -0
  59. package/src/array/impl/array-utils-length-constraint-preservation.test.mts +287 -0
  60. package/src/array/impl/array-utils-modification.mts +72 -57
  61. package/src/array/impl/array-utils-modification.test.mts +93 -6
  62. package/src/array/impl/array-utils-reducing-value.mts +5 -5
  63. package/src/array/impl/array-utils-slicing.mts +65 -43
  64. package/src/array/impl/array-utils-slicing.test.mts +55 -0
  65. package/src/array/impl/array-utils-transformation.mts +66 -39
  66. package/src/array/impl/array-utils-transformation.test.mts +62 -16
  67. package/src/array/impl/array-utils-validation.mts +2 -162
  68. package/src/array/impl/array-utils-validation.test.mts +0 -371
  69. package/src/array/impl/index.mts +2 -0
  70. package/src/collections/queue.test.mts +1 -1
  71. package/src/string/str.mts +69 -69
  72. package/src/string/str.test.mts +40 -40
@@ -33,30 +33,30 @@ export namespace Str {
33
33
  * ```ts
34
34
  * const input: string = 'very-secret-password';
35
35
  *
36
- * assert.isTrue(Str.isMinLengthString(input, 12));
36
+ * assert.isTrue(Str.isMinLengthString(12, input));
37
37
  *
38
- * assert.isFalse(Str.isMinLengthString('short', 12));
38
+ * assert.isFalse(Str.isMinLengthString(12, 'short'));
39
39
  *
40
- * if (Str.isMinLengthString(input, 12)) {
40
+ * if (Str.isMinLengthString(12, input)) {
41
41
  * const nonEmpty: NonEmptyString = input; // OK (12 >= 1)
42
42
  *
43
43
  * assert.isTrue(nonEmpty.length >= 12);
44
44
  * }
45
45
  * ```
46
46
  *
47
- * @template S - The input string type (literal types are preserved).
48
47
  * @template MinLength - The minimum number of characters (inclusive).
49
- * @param s - The string to check.
48
+ * @template S - The input string type (literal types are preserved).
50
49
  * @param minLength - The minimum number of characters (inclusive).
50
+ * @param s - The string to check.
51
51
  * @returns `true` if `s.length >= minLength`, `false` otherwise. When `true`,
52
52
  * TypeScript narrows `s` to `MinLengthString<MinLength> & S`.
53
53
  */
54
54
  export const isMinLengthString = <
55
- S extends string,
56
55
  MinLength extends SupportedLength,
56
+ S extends string,
57
57
  >(
58
- s: S,
59
58
  minLength: MinLength,
59
+ s: S,
60
60
  ): s is MinLengthString<MinLength> & S => s.length >= minLength;
61
61
 
62
62
  /**
@@ -75,30 +75,30 @@ export namespace Str {
75
75
  * ```ts
76
76
  * const input: string = 'noshiro';
77
77
  *
78
- * assert.isTrue(Str.isMaxLengthString(input, 32));
78
+ * assert.isTrue(Str.isMaxLengthString(32, input));
79
79
  *
80
- * assert.isFalse(Str.isMaxLengthString(input, 3));
80
+ * assert.isFalse(Str.isMaxLengthString(3, input));
81
81
  *
82
- * if (Str.isMaxLengthString(input, 32)) {
82
+ * if (Str.isMaxLengthString(32, input)) {
83
83
  * const relaxed: MaxLengthString<64> = input; // OK (32 <= 64)
84
84
  *
85
85
  * assert.isTrue(relaxed.length <= 32);
86
86
  * }
87
87
  * ```
88
88
  *
89
- * @template S - The input string type (literal types are preserved).
90
89
  * @template MaxLength - The maximum number of characters (inclusive).
91
- * @param s - The string to check.
90
+ * @template S - The input string type (literal types are preserved).
92
91
  * @param maxLength - The maximum number of characters (inclusive).
92
+ * @param s - The string to check.
93
93
  * @returns `true` if `s.length <= maxLength`, `false` otherwise. When `true`,
94
94
  * TypeScript narrows `s` to `MaxLengthString<MaxLength> & S`.
95
95
  */
96
96
  export const isMaxLengthString = <
97
- S extends string,
98
97
  MaxLength extends SupportedLength,
98
+ S extends string,
99
99
  >(
100
- s: S,
101
100
  maxLength: MaxLength,
101
+ s: S,
102
102
  ): s is MaxLengthString<MaxLength> & S => s.length <= maxLength;
103
103
 
104
104
  /**
@@ -118,35 +118,35 @@ export namespace Str {
118
118
  * ```ts
119
119
  * const input: string = 'user-12345678';
120
120
  *
121
- * assert.isTrue(Str.isBoundedLengthString(input, 8, 16));
121
+ * assert.isTrue(Str.isBoundedLengthString(8, 16, input));
122
122
  *
123
- * assert.isFalse(Str.isBoundedLengthString('user', 8, 16));
123
+ * assert.isFalse(Str.isBoundedLengthString(8, 16, 'user'));
124
124
  *
125
- * if (Str.isBoundedLengthString(input, 8, 16)) {
125
+ * if (Str.isBoundedLengthString(8, 16, input)) {
126
126
  * const userId: BoundedLengthString<1, 255> = input; // OK ([8, 16] ⊆ [1, 255])
127
127
  *
128
128
  * assert.isTrue(userId.length >= 8 && userId.length <= 16);
129
129
  * }
130
130
  * ```
131
131
  *
132
- * @template S - The input string type (literal types are preserved).
133
132
  * @template MinLength - The minimum number of characters (inclusive).
134
133
  * @template MaxLength - The maximum number of characters (inclusive).
135
- * @param s - The string to check.
134
+ * @template S - The input string type (literal types are preserved).
136
135
  * @param minLength - The minimum number of characters (inclusive).
137
136
  * @param maxLength - The maximum number of characters (inclusive).
137
+ * @param s - The string to check.
138
138
  * @returns `true` if `minLength <= s.length && s.length <= maxLength`, `false`
139
139
  * otherwise. When `true`, TypeScript narrows `s` to
140
140
  * `BoundedLengthString<MinLength, MaxLength> & S`.
141
141
  */
142
142
  export const isBoundedLengthString = <
143
- S extends string,
144
143
  MinLength extends SupportedLength,
145
144
  MaxLength extends SupportedLength,
145
+ S extends string,
146
146
  >(
147
- s: S,
148
147
  minLength: MinLength,
149
148
  maxLength: MaxLength,
149
+ s: S,
150
150
  ): s is BoundedLengthString<MinLength, MaxLength> & S =>
151
151
  s.length >= minLength && s.length <= maxLength;
152
152
 
@@ -167,30 +167,30 @@ export namespace Str {
167
167
  * ```ts
168
168
  * const input: string = 'JP';
169
169
  *
170
- * assert.isTrue(Str.isFixedLengthString(input, 2));
170
+ * assert.isTrue(Str.isFixedLengthString(2, input));
171
171
  *
172
- * assert.isFalse(Str.isFixedLengthString(input, 3));
172
+ * assert.isFalse(Str.isFixedLengthString(3, input));
173
173
  *
174
- * if (Str.isFixedLengthString(input, 2)) {
174
+ * if (Str.isFixedLengthString(2, input)) {
175
175
  * const atMost5: MaxLengthString<5> = input; // OK (2 <= 5)
176
176
  *
177
177
  * assert.isTrue(atMost5.length === 2);
178
178
  * }
179
179
  * ```
180
180
  *
181
- * @template S - The input string type (literal types are preserved).
182
181
  * @template Length - The exact number of characters.
183
- * @param s - The string to check.
182
+ * @template S - The input string type (literal types are preserved).
184
183
  * @param length - The exact number of characters.
184
+ * @param s - The string to check.
185
185
  * @returns `true` if `s.length === length`, `false` otherwise. When `true`,
186
186
  * TypeScript narrows `s` to `FixedLengthString<Length> & S`.
187
187
  */
188
188
  export const isFixedLengthString = <
189
- S extends string,
190
189
  Length extends SupportedLength,
190
+ S extends string,
191
191
  >(
192
- s: S,
193
192
  length: Length,
193
+ s: S,
194
194
  ): s is FixedLengthString<Length> & S => s.length === length;
195
195
 
196
196
  /**
@@ -207,7 +207,7 @@ export namespace Str {
207
207
  * @example
208
208
  *
209
209
  * ```ts
210
- * const password = Str.asMinLengthString('very-secret-password', 12);
210
+ * const password = Str.asMinLengthString(12, 'very-secret-password');
211
211
  *
212
212
  * const nonEmpty: NonEmptyString = password; // OK (>= 1)
213
213
  *
@@ -218,20 +218,20 @@ export namespace Str {
218
218
  *
219
219
  * assert.strictEqual(asPassword('another-secret'), 'another-secret');
220
220
  *
221
- * assert.throws(() => Str.asMinLengthString('short', 12)); // length 5 < 12
221
+ * assert.throws(() => Str.asMinLengthString(12, 'short')); // length 5 < 12
222
222
  * ```
223
223
  *
224
- * @template S - The input string type (literal types are preserved).
225
224
  * @template MinLength - The minimum number of characters (inclusive).
226
- * @param s - The string to cast.
225
+ * @template S - The input string type (literal types are preserved).
227
226
  * @param minLength - The minimum number of characters (inclusive).
227
+ * @param s - The string to cast.
228
228
  * @returns `s` typed as `MinLengthString<MinLength> & S`.
229
229
  * @throws {TypeError} If `s.length < minLength`.
230
230
  */
231
231
  export function asMinLengthString<
232
- S extends string,
233
232
  MinLength extends SupportedLength,
234
- >(s: S, minLength: MinLength): MinLengthString<MinLength> & S;
233
+ S extends string,
234
+ >(minLength: MinLength, s: S): MinLengthString<MinLength> & S;
235
235
 
236
236
  // Curried version
237
237
  export function asMinLengthString<MinLength extends SupportedLength>(
@@ -240,7 +240,7 @@ export namespace Str {
240
240
 
241
241
  export function asMinLengthString(
242
242
  ...args:
243
- | readonly [s: string, minLength: SupportedLength]
243
+ | readonly [minLength: SupportedLength, s: string]
244
244
  | readonly [minLength: SupportedLength]
245
245
  ): string | ((s: string) => string) {
246
246
  switch (args.length) {
@@ -248,17 +248,17 @@ export namespace Str {
248
248
  return asMinLengthStringImpl(...args);
249
249
 
250
250
  case 1:
251
- return (s) => asMinLengthStringImpl(s, ...args);
251
+ return (s) => asMinLengthStringImpl(args[0], s);
252
252
  }
253
253
  }
254
254
 
255
255
  const asMinLengthStringImpl = (
256
- s: string,
257
256
  minLength: SupportedLength,
257
+ s: string,
258
258
  ): string => {
259
259
  const actualLength = s.length;
260
260
 
261
- if (!isMinLengthString(s, minLength)) {
261
+ if (!isMinLengthString(minLength, s)) {
262
262
  throw new TypeError(
263
263
  `Expected a string of length >= ${minLength}, got a string of length ${actualLength}`,
264
264
  );
@@ -281,7 +281,7 @@ export namespace Str {
281
281
  * @example
282
282
  *
283
283
  * ```ts
284
- * const userName = Str.asMaxLengthString('noshiro', 32);
284
+ * const userName = Str.asMaxLengthString(32, 'noshiro');
285
285
  *
286
286
  * const relaxed: MaxLengthString<64> = userName; // OK (32 <= 64)
287
287
  *
@@ -292,20 +292,20 @@ export namespace Str {
292
292
  *
293
293
  * assert.strictEqual(asUserName('another-user'), 'another-user');
294
294
  *
295
- * assert.throws(() => Str.asMaxLengthString('noshiro', 3)); // length 7 > 3
295
+ * assert.throws(() => Str.asMaxLengthString(3, 'noshiro')); // length 7 > 3
296
296
  * ```
297
297
  *
298
- * @template S - The input string type (literal types are preserved).
299
298
  * @template MaxLength - The maximum number of characters (inclusive).
300
- * @param s - The string to cast.
299
+ * @template S - The input string type (literal types are preserved).
301
300
  * @param maxLength - The maximum number of characters (inclusive).
301
+ * @param s - The string to cast.
302
302
  * @returns `s` typed as `MaxLengthString<MaxLength> & S`.
303
303
  * @throws {TypeError} If `s.length > maxLength`.
304
304
  */
305
305
  export function asMaxLengthString<
306
- S extends string,
307
306
  MaxLength extends SupportedLength,
308
- >(s: S, maxLength: MaxLength): MaxLengthString<MaxLength> & S;
307
+ S extends string,
308
+ >(maxLength: MaxLength, s: S): MaxLengthString<MaxLength> & S;
309
309
 
310
310
  // Curried version
311
311
  export function asMaxLengthString<MaxLength extends SupportedLength>(
@@ -314,7 +314,7 @@ export namespace Str {
314
314
 
315
315
  export function asMaxLengthString(
316
316
  ...args:
317
- | readonly [s: string, maxLength: SupportedLength]
317
+ | readonly [maxLength: SupportedLength, s: string]
318
318
  | readonly [maxLength: SupportedLength]
319
319
  ): string | ((s: string) => string) {
320
320
  switch (args.length) {
@@ -322,17 +322,17 @@ export namespace Str {
322
322
  return asMaxLengthStringImpl(...args);
323
323
 
324
324
  case 1:
325
- return (s) => asMaxLengthStringImpl(s, ...args);
325
+ return (s) => asMaxLengthStringImpl(args[0], s);
326
326
  }
327
327
  }
328
328
 
329
329
  const asMaxLengthStringImpl = (
330
- s: string,
331
330
  maxLength: SupportedLength,
331
+ s: string,
332
332
  ): string => {
333
333
  const actualLength = s.length;
334
334
 
335
- if (!isMaxLengthString(s, maxLength)) {
335
+ if (!isMaxLengthString(maxLength, s)) {
336
336
  throw new TypeError(
337
337
  `Expected a string of length <= ${maxLength}, got a string of length ${actualLength}`,
338
338
  );
@@ -357,7 +357,7 @@ export namespace Str {
357
357
  * @example
358
358
  *
359
359
  * ```ts
360
- * const userId = Str.asBoundedLengthString('user-12345678', 8, 16);
360
+ * const userId = Str.asBoundedLengthString(8, 16, 'user-12345678');
361
361
  *
362
362
  * const relaxed: BoundedLengthString<1, 255> = userId; // OK ([8, 16] ⊆ [1, 255])
363
363
  *
@@ -368,26 +368,26 @@ export namespace Str {
368
368
  *
369
369
  * assert.strictEqual(asUserId('user-87654321'), 'user-87654321');
370
370
  *
371
- * assert.throws(() => Str.asBoundedLengthString('user', 8, 16)); // length 4 < 8
371
+ * assert.throws(() => Str.asBoundedLengthString(8, 16, 'user')); // length 4 < 8
372
372
  * ```
373
373
  *
374
- * @template S - The input string type (literal types are preserved).
375
374
  * @template MinLength - The minimum number of characters (inclusive).
376
375
  * @template MaxLength - The maximum number of characters (inclusive).
377
- * @param s - The string to cast.
376
+ * @template S - The input string type (literal types are preserved).
378
377
  * @param minLength - The minimum number of characters (inclusive).
379
378
  * @param maxLength - The maximum number of characters (inclusive).
379
+ * @param s - The string to cast.
380
380
  * @returns `s` typed as `BoundedLengthString<MinLength, MaxLength> & S`.
381
381
  * @throws {TypeError} If `s.length < minLength` or `s.length > maxLength`.
382
382
  */
383
383
  export function asBoundedLengthString<
384
- S extends string,
385
384
  MinLength extends SupportedLength,
386
385
  MaxLength extends SupportedLength,
386
+ S extends string,
387
387
  >(
388
- s: S,
389
388
  minLength: MinLength,
390
389
  maxLength: MaxLength,
390
+ s: S,
391
391
  ): BoundedLengthString<MinLength, MaxLength> & S;
392
392
 
393
393
  // Curried version
@@ -402,9 +402,9 @@ export namespace Str {
402
402
  export function asBoundedLengthString(
403
403
  ...args:
404
404
  | readonly [
405
- s: string,
406
405
  minLength: SupportedLength,
407
406
  maxLength: SupportedLength,
407
+ s: string,
408
408
  ]
409
409
  | readonly [minLength: SupportedLength, maxLength: SupportedLength]
410
410
  ): string | ((s: string) => string) {
@@ -413,18 +413,18 @@ export namespace Str {
413
413
  return asBoundedLengthStringImpl(...args);
414
414
 
415
415
  case 2:
416
- return (s) => asBoundedLengthStringImpl(s, ...args);
416
+ return (s) => asBoundedLengthStringImpl(...args, s);
417
417
  }
418
418
  }
419
419
 
420
420
  const asBoundedLengthStringImpl = (
421
- s: string,
422
421
  minLength: SupportedLength,
423
422
  maxLength: SupportedLength,
423
+ s: string,
424
424
  ): string => {
425
425
  const actualLength = s.length;
426
426
 
427
- if (!isBoundedLengthString(s, minLength, maxLength)) {
427
+ if (!isBoundedLengthString(minLength, maxLength, s)) {
428
428
  throw new TypeError(
429
429
  `Expected a string of length in [${minLength}, ${maxLength}], got a string of length ${actualLength}`,
430
430
  );
@@ -447,7 +447,7 @@ export namespace Str {
447
447
  * @example
448
448
  *
449
449
  * ```ts
450
- * const countryCode = Str.asFixedLengthString('JP', 2);
450
+ * const countryCode = Str.asFixedLengthString(2, 'JP');
451
451
  *
452
452
  * const atMost5: MaxLengthString<5> = countryCode; // OK (2 <= 5)
453
453
  *
@@ -458,20 +458,20 @@ export namespace Str {
458
458
  *
459
459
  * assert.strictEqual(asCountryCode('US'), 'US');
460
460
  *
461
- * assert.throws(() => Str.asFixedLengthString('JP', 3)); // length 2 !== 3
461
+ * assert.throws(() => Str.asFixedLengthString(3, 'JP')); // length 2 !== 3
462
462
  * ```
463
463
  *
464
- * @template S - The input string type (literal types are preserved).
465
464
  * @template Length - The exact number of characters.
466
- * @param s - The string to cast.
465
+ * @template S - The input string type (literal types are preserved).
467
466
  * @param length - The exact number of characters.
467
+ * @param s - The string to cast.
468
468
  * @returns `s` typed as `FixedLengthString<Length> & S`.
469
469
  * @throws {TypeError} If `s.length !== length`.
470
470
  */
471
471
  export function asFixedLengthString<
472
- S extends string,
473
472
  Length extends SupportedLength,
474
- >(s: S, length: Length): FixedLengthString<Length> & S;
473
+ S extends string,
474
+ >(length: Length, s: S): FixedLengthString<Length> & S;
475
475
 
476
476
  // Curried version
477
477
  export function asFixedLengthString<Length extends SupportedLength>(
@@ -480,7 +480,7 @@ export namespace Str {
480
480
 
481
481
  export function asFixedLengthString(
482
482
  ...args:
483
- | readonly [s: string, length: SupportedLength]
483
+ | readonly [length: SupportedLength, s: string]
484
484
  | readonly [length: SupportedLength]
485
485
  ): string | ((s: string) => string) {
486
486
  switch (args.length) {
@@ -488,17 +488,17 @@ export namespace Str {
488
488
  return asFixedLengthStringImpl(...args);
489
489
 
490
490
  case 1:
491
- return (s) => asFixedLengthStringImpl(s, ...args);
491
+ return (s) => asFixedLengthStringImpl(args[0], s);
492
492
  }
493
493
  }
494
494
 
495
495
  const asFixedLengthStringImpl = (
496
- s: string,
497
496
  length: SupportedLength,
497
+ s: string,
498
498
  ): string => {
499
499
  const actualLength = s.length;
500
500
 
501
- if (!isFixedLengthString(s, length)) {
501
+ if (!isFixedLengthString(length, s)) {
502
502
  throw new TypeError(
503
503
  `Expected a string of length ${length}, got a string of length ${actualLength}`,
504
504
  );
@@ -537,7 +537,7 @@ export namespace Str {
537
537
  export const asNonEmptyString = <S extends string>(
538
538
  s: S,
539
539
  ): NonEmptyString & S => {
540
- if (!isMinLengthString(s, 1)) {
540
+ if (!isMinLengthString(1, s)) {
541
541
  throw new TypeError('Expected a non-empty string, got an empty string');
542
542
  }
543
543
 
@@ -10,31 +10,31 @@ import { Str } from './str.mjs';
10
10
 
11
11
  describe(Str.isMinLengthString, () => {
12
12
  test('should return true when the string is long enough', () => {
13
- assert.isTrue(Str.isMinLengthString('hello', 3));
13
+ assert.isTrue(Str.isMinLengthString(3, 'hello'));
14
14
 
15
- assert.isTrue(Str.isMinLengthString('hello', 5));
15
+ assert.isTrue(Str.isMinLengthString(5, 'hello'));
16
16
 
17
- assert.isTrue(Str.isMinLengthString('', 0));
17
+ assert.isTrue(Str.isMinLengthString(0, ''));
18
18
 
19
- assert.isTrue(Str.isMinLengthString(' ', 1)); // Space counts
19
+ assert.isTrue(Str.isMinLengthString(1, ' ')); // Space counts
20
20
  });
21
21
 
22
22
  test('should return false when the string is too short', () => {
23
- assert.isFalse(Str.isMinLengthString('hi', 3));
23
+ assert.isFalse(Str.isMinLengthString(3, 'hi'));
24
24
 
25
- assert.isFalse(Str.isMinLengthString('', 1));
25
+ assert.isFalse(Str.isMinLengthString(1, ''));
26
26
  });
27
27
 
28
28
  test('should measure length in UTF-16 code units', () => {
29
- assert.isTrue(Str.isMinLengthString('🎉', 2)); // Surrogate pair
29
+ assert.isTrue(Str.isMinLengthString(2, '🎉')); // Surrogate pair
30
30
 
31
- assert.isFalse(Str.isMinLengthString('🎉', 3));
31
+ assert.isFalse(Str.isMinLengthString(3, '🎉'));
32
32
  });
33
33
 
34
34
  test('should act as a type guard', () => {
35
35
  const value: string = 'very-secret-password';
36
36
 
37
- if (Str.isMinLengthString(value, 12)) {
37
+ if (Str.isMinLengthString(12, value)) {
38
38
  expectType<typeof value, MinLengthString<12>>('<=');
39
39
 
40
40
  expectType<typeof value, NonEmptyString>('<='); // 12 >= 1
@@ -48,7 +48,7 @@ describe(Str.isMinLengthString, () => {
48
48
  test('should preserve literal string types', () => {
49
49
  const literal = 'hello';
50
50
 
51
- if (Str.isMinLengthString(literal, 3)) {
51
+ if (Str.isMinLengthString(3, literal)) {
52
52
  expectType<typeof literal, 'hello'>('<=');
53
53
 
54
54
  expectType<typeof literal, MinLengthString<3>>('<=');
@@ -58,29 +58,29 @@ describe(Str.isMinLengthString, () => {
58
58
 
59
59
  describe(Str.isMaxLengthString, () => {
60
60
  test('should return true when the string is short enough', () => {
61
- assert.isTrue(Str.isMaxLengthString('hello', 10));
61
+ assert.isTrue(Str.isMaxLengthString(10, 'hello'));
62
62
 
63
- assert.isTrue(Str.isMaxLengthString('hello', 5));
63
+ assert.isTrue(Str.isMaxLengthString(5, 'hello'));
64
64
 
65
- assert.isTrue(Str.isMaxLengthString('', 0));
65
+ assert.isTrue(Str.isMaxLengthString(0, ''));
66
66
  });
67
67
 
68
68
  test('should return false when the string is too long', () => {
69
- assert.isFalse(Str.isMaxLengthString('hello', 3));
69
+ assert.isFalse(Str.isMaxLengthString(3, 'hello'));
70
70
 
71
- assert.isFalse(Str.isMaxLengthString(' ', 0));
71
+ assert.isFalse(Str.isMaxLengthString(0, ' '));
72
72
  });
73
73
 
74
74
  test('should measure length in UTF-16 code units', () => {
75
- assert.isFalse(Str.isMaxLengthString('🎉', 1)); // Surrogate pair
75
+ assert.isFalse(Str.isMaxLengthString(1, '🎉')); // Surrogate pair
76
76
 
77
- assert.isTrue(Str.isMaxLengthString('🎉', 2));
77
+ assert.isTrue(Str.isMaxLengthString(2, '🎉'));
78
78
  });
79
79
 
80
80
  test('should act as a type guard', () => {
81
81
  const value: string = 'noshiro';
82
82
 
83
- if (Str.isMaxLengthString(value, 32)) {
83
+ if (Str.isMaxLengthString(32, value)) {
84
84
  expectType<typeof value, MaxLengthString<32>>('<=');
85
85
 
86
86
  expectType<typeof value, MaxLengthString<64>>('<='); // 32 <= 64
@@ -94,25 +94,25 @@ describe(Str.isMaxLengthString, () => {
94
94
 
95
95
  describe(Str.isBoundedLengthString, () => {
96
96
  test('should return true when the length is within the range', () => {
97
- assert.isTrue(Str.isBoundedLengthString('user-12345678', 8, 16));
97
+ assert.isTrue(Str.isBoundedLengthString(8, 16, 'user-12345678'));
98
98
 
99
- assert.isTrue(Str.isBoundedLengthString('12345678', 8, 16)); // Lower bound (inclusive)
99
+ assert.isTrue(Str.isBoundedLengthString(8, 16, '12345678')); // Lower bound (inclusive)
100
100
 
101
- assert.isTrue(Str.isBoundedLengthString('1234567890123456', 8, 16)); // Upper bound (inclusive)
101
+ assert.isTrue(Str.isBoundedLengthString(8, 16, '1234567890123456')); // Upper bound (inclusive)
102
102
 
103
- assert.isTrue(Str.isBoundedLengthString('', 0, 0));
103
+ assert.isTrue(Str.isBoundedLengthString(0, 0, ''));
104
104
  });
105
105
 
106
106
  test('should return false when the length is out of range', () => {
107
- assert.isFalse(Str.isBoundedLengthString('user', 8, 16));
107
+ assert.isFalse(Str.isBoundedLengthString(8, 16, 'user'));
108
108
 
109
- assert.isFalse(Str.isBoundedLengthString('12345678901234567', 8, 16));
109
+ assert.isFalse(Str.isBoundedLengthString(8, 16, '12345678901234567'));
110
110
  });
111
111
 
112
112
  test('should act as a type guard', () => {
113
113
  const value: string = 'user-12345678';
114
114
 
115
- if (Str.isBoundedLengthString(value, 8, 16)) {
115
+ if (Str.isBoundedLengthString(8, 16, value)) {
116
116
  expectType<typeof value, BoundedLengthString<8, 16>>('<=');
117
117
 
118
118
  expectType<typeof value, BoundedLengthString<1, 255>>('<='); // [8, 16] ⊆ [1, 255]
@@ -130,25 +130,25 @@ describe(Str.isBoundedLengthString, () => {
130
130
 
131
131
  describe(Str.isFixedLengthString, () => {
132
132
  test('should return true only for the exact length', () => {
133
- assert.isTrue(Str.isFixedLengthString('JP', 2));
133
+ assert.isTrue(Str.isFixedLengthString(2, 'JP'));
134
134
 
135
- assert.isTrue(Str.isFixedLengthString('', 0));
135
+ assert.isTrue(Str.isFixedLengthString(0, ''));
136
136
 
137
- assert.isFalse(Str.isFixedLengthString('JPN', 2));
137
+ assert.isFalse(Str.isFixedLengthString(2, 'JPN'));
138
138
 
139
- assert.isFalse(Str.isFixedLengthString('J', 2));
139
+ assert.isFalse(Str.isFixedLengthString(2, 'J'));
140
140
  });
141
141
 
142
142
  test('should measure length in UTF-16 code units', () => {
143
- assert.isTrue(Str.isFixedLengthString('🎉', 2)); // Surrogate pair
143
+ assert.isTrue(Str.isFixedLengthString(2, '🎉')); // Surrogate pair
144
144
 
145
- assert.isFalse(Str.isFixedLengthString('🎉', 1));
145
+ assert.isFalse(Str.isFixedLengthString(1, '🎉'));
146
146
  });
147
147
 
148
148
  test('should act as a type guard', () => {
149
149
  const value: string = 'JP';
150
150
 
151
- if (Str.isFixedLengthString(value, 2)) {
151
+ if (Str.isFixedLengthString(2, value)) {
152
152
  expectType<typeof value, FixedLengthString<2>>('<=');
153
153
 
154
154
  expectType<typeof value, BoundedLengthString<2, 2>>('<=');
@@ -166,7 +166,7 @@ describe(Str.isFixedLengthString, () => {
166
166
 
167
167
  describe('Str length-bounded casts', () => {
168
168
  test('asMinLengthString returns the value and narrows its type', () => {
169
- const result = Str.asMinLengthString('very-secret', 3);
169
+ const result = Str.asMinLengthString(3, 'very-secret');
170
170
 
171
171
  expectType<typeof result, MinLengthString<3>>('<=');
172
172
 
@@ -174,11 +174,11 @@ describe('Str length-bounded casts', () => {
174
174
  });
175
175
 
176
176
  test('asMinLengthString throws when too short', () => {
177
- assert.throws(() => Str.asMinLengthString('hi', 3), TypeError);
177
+ assert.throws(() => Str.asMinLengthString(3, 'hi'), TypeError);
178
178
  });
179
179
 
180
180
  test('asMaxLengthString returns the value and narrows its type', () => {
181
- const result = Str.asMaxLengthString('noshiro', 32);
181
+ const result = Str.asMaxLengthString(32, 'noshiro');
182
182
 
183
183
  expectType<typeof result, MaxLengthString<32>>('<=');
184
184
 
@@ -186,11 +186,11 @@ describe('Str length-bounded casts', () => {
186
186
  });
187
187
 
188
188
  test('asMaxLengthString throws when too long', () => {
189
- assert.throws(() => Str.asMaxLengthString('noshiro', 3), TypeError);
189
+ assert.throws(() => Str.asMaxLengthString(3, 'noshiro'), TypeError);
190
190
  });
191
191
 
192
192
  test('asBoundedLengthString returns the value and narrows its type', () => {
193
- const result = Str.asBoundedLengthString('user-12345678', 8, 16);
193
+ const result = Str.asBoundedLengthString(8, 16, 'user-12345678');
194
194
 
195
195
  expectType<typeof result, BoundedLengthString<8, 16>>('<=');
196
196
 
@@ -198,11 +198,11 @@ describe('Str length-bounded casts', () => {
198
198
  });
199
199
 
200
200
  test('asBoundedLengthString throws when out of range', () => {
201
- assert.throws(() => Str.asBoundedLengthString('user', 8, 16), TypeError);
201
+ assert.throws(() => Str.asBoundedLengthString(8, 16, 'user'), TypeError);
202
202
  });
203
203
 
204
204
  test('asFixedLengthString returns the value and narrows its type', () => {
205
- const result = Str.asFixedLengthString('JP', 2);
205
+ const result = Str.asFixedLengthString(2, 'JP');
206
206
 
207
207
  expectType<typeof result, FixedLengthString<2>>('<=');
208
208
 
@@ -210,7 +210,7 @@ describe('Str length-bounded casts', () => {
210
210
  });
211
211
 
212
212
  test('asFixedLengthString throws when the length differs', () => {
213
- assert.throws(() => Str.asFixedLengthString('JP', 3), TypeError);
213
+ assert.throws(() => Str.asFixedLengthString(3, 'JP'), TypeError);
214
214
  });
215
215
  });
216
216