ts-data-forge 12.0.0 → 12.1.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.
@@ -1,4 +1,4 @@
1
- import { type BoundedLengthArray, type FixedLengthArray, type MaxLengthArray, type MinLengthArray, type SupportedLength } from 'ts-type-forge';
1
+ import { type BoundedLengthArray, type FixedLengthArray, type MaxLengthArray, type MinLengthArray, type NonEmptyArray, type SupportedLength } from 'ts-type-forge';
2
2
  /**
3
3
  * Casts an array to `FixedLengthArray<Length, E>` after checking that it has
4
4
  * exactly `length` elements.
@@ -9,6 +9,9 @@ import { type BoundedLengthArray, type FixedLengthArray, type MaxLengthArray, ty
9
9
  * structural tuple prefix (in-range indexed access without `undefined` under
10
10
  * `noUncheckedIndexedAccess`).
11
11
  *
12
+ * Supports a curried overload: calling it with only `length` returns a
13
+ * function that casts an array, which is convenient for `pipe`/`map`.
14
+ *
12
15
  * @example
13
16
  *
14
17
  * ```ts
@@ -17,6 +20,10 @@ import { type BoundedLengthArray, type FixedLengthArray, type MaxLengthArray, ty
17
20
  * const atMost5: MaxLengthArray<5, number> = rgb; // OK (3 <= 5)
18
21
  * const red: number = rgb[0]; // OK — no `undefined`
19
22
  *
23
+ * // curried version
24
+ * const asRgb = Arr.asFixedLengthArray(3);
25
+ * const green = asRgb([0, 255, 0]);
26
+ *
20
27
  * // Arr.asFixedLengthArray([255, 128], 3); // throws TypeError
21
28
  * ```
22
29
  *
@@ -27,7 +34,8 @@ import { type BoundedLengthArray, type FixedLengthArray, type MaxLengthArray, ty
27
34
  * @returns `xs` typed as `FixedLengthArray<Length, Xs[number]> & Xs`.
28
35
  * @throws {TypeError} If `xs.length !== length`.
29
36
  */
30
- export declare const asFixedLengthArray: <Xs extends readonly unknown[], Length extends SupportedLength>(xs: Xs, length: Length) => FixedLengthArray<Length, Xs[number]> & Xs;
37
+ export declare function asFixedLengthArray<Xs extends readonly unknown[], Length extends SupportedLength>(xs: Xs, length: Length): FixedLengthArray<Length, Xs[number]> & Xs;
38
+ export declare function asFixedLengthArray<Length extends SupportedLength>(length: Length): <Xs extends readonly unknown[]>(xs: Xs) => FixedLengthArray<Length, Xs[number]> & Xs;
31
39
  /**
32
40
  * Casts an array to `MinLengthArray<MinLength, E>` after checking that it has
33
41
  * at least `minLength` elements.
@@ -38,6 +46,9 @@ export declare const asFixedLengthArray: <Xs extends readonly unknown[], Length
38
46
  * structural tuple prefix (indexed access below `min(N, 10)` without
39
47
  * `undefined` under `noUncheckedIndexedAccess`).
40
48
  *
49
+ * Supports a curried overload: calling it with only `minLength` returns a
50
+ * function that casts an array, which is convenient for `pipe`/`map`.
51
+ *
41
52
  * @example
42
53
  *
43
54
  * ```ts
@@ -46,6 +57,10 @@ export declare const asFixedLengthArray: <Xs extends readonly unknown[], Length
46
57
  * const nonEmpty: MinLengthArray<1, number> = history; // OK (3 >= 1)
47
58
  * const first: number = history[0]; // OK — no `undefined`
48
59
  *
60
+ * // curried version
61
+ * const asHistory = Arr.asMinLengthArray(3);
62
+ * const next = asHistory([4, 5, 6, 7]);
63
+ *
49
64
  * // Arr.asMinLengthArray([0], 3); // throws TypeError
50
65
  * ```
51
66
  *
@@ -56,7 +71,8 @@ export declare const asFixedLengthArray: <Xs extends readonly unknown[], Length
56
71
  * @returns `xs` typed as `MinLengthArray<MinLength, Xs[number]> & Xs`.
57
72
  * @throws {TypeError} If `xs.length < minLength`.
58
73
  */
59
- export declare const asMinLengthArray: <Xs extends readonly unknown[], MinLength extends SupportedLength>(xs: Xs, minLength: MinLength) => MinLengthArray<MinLength, Xs[number]> & Xs;
74
+ export declare function asMinLengthArray<Xs extends readonly unknown[], MinLength extends SupportedLength>(xs: Xs, minLength: MinLength): MinLengthArray<MinLength, Xs[number]> & Xs;
75
+ export declare function asMinLengthArray<MinLength extends SupportedLength>(minLength: MinLength): <Xs extends readonly unknown[]>(xs: Xs) => MinLengthArray<MinLength, Xs[number]> & Xs;
60
76
  /**
61
77
  * Casts an array to `MaxLengthArray<MaxLength, E>` after checking that it has
62
78
  * at most `maxLength` elements.
@@ -65,6 +81,9 @@ export declare const asMinLengthArray: <Xs extends readonly unknown[], MinLength
65
81
  * length is verified at runtime, and the original array type (e.g. tuple
66
82
  * types) is preserved via intersection.
67
83
  *
84
+ * Supports a curried overload: calling it with only `maxLength` returns a
85
+ * function that casts an array, which is convenient for `pipe`/`map`.
86
+ *
68
87
  * @example
69
88
  *
70
89
  * ```ts
@@ -72,6 +91,10 @@ export declare const asMinLengthArray: <Xs extends readonly unknown[], MinLength
72
91
  *
73
92
  * const relaxed: MaxLengthArray<16, string> = tags; // OK (8 <= 16)
74
93
  *
94
+ * // curried version
95
+ * const asTags = Arr.asMaxLengthArray(8);
96
+ * const more = asTags(['d', 'e']);
97
+ *
75
98
  * // Arr.asMaxLengthArray(['a', 'b', 'c'], 2); // throws TypeError
76
99
  * ```
77
100
  *
@@ -82,7 +105,8 @@ export declare const asMinLengthArray: <Xs extends readonly unknown[], MinLength
82
105
  * @returns `xs` typed as `MaxLengthArray<MaxLength, Xs[number]> & Xs`.
83
106
  * @throws {TypeError} If `xs.length > maxLength`.
84
107
  */
85
- export declare const asMaxLengthArray: <Xs extends readonly unknown[], MaxLength extends SupportedLength>(xs: Xs, maxLength: MaxLength) => MaxLengthArray<MaxLength, Xs[number]> & Xs;
108
+ export declare function asMaxLengthArray<Xs extends readonly unknown[], MaxLength extends SupportedLength>(xs: Xs, maxLength: MaxLength): MaxLengthArray<MaxLength, Xs[number]> & Xs;
109
+ export declare function asMaxLengthArray<MaxLength extends SupportedLength>(maxLength: MaxLength): <Xs extends readonly unknown[]>(xs: Xs) => MaxLengthArray<MaxLength, Xs[number]> & Xs;
86
110
  /**
87
111
  * Casts an array to `BoundedLengthArray<MinLength, MaxLength, E>` after
88
112
  * checking that its length is within the inclusive range
@@ -93,6 +117,10 @@ export declare const asMaxLengthArray: <Xs extends readonly unknown[], MaxLength
93
117
  * at runtime, and the original array type (e.g. tuple types) is preserved via
94
118
  * intersection.
95
119
  *
120
+ * Supports a curried overload: calling it with only `minLength` and
121
+ * `maxLength` returns a function that casts an array, which is convenient for
122
+ * `pipe`/`map`.
123
+ *
96
124
  * @example
97
125
  *
98
126
  * ```ts
@@ -100,6 +128,10 @@ export declare const asMaxLengthArray: <Xs extends readonly unknown[], MaxLength
100
128
  *
101
129
  * const relaxed: BoundedLengthArray<0, 100, number> = selection; // OK
102
130
  *
131
+ * // curried version
132
+ * const asSelection = Arr.asBoundedLengthArray(1, 5);
133
+ * const next = asSelection([4, 5]);
134
+ *
103
135
  * // Arr.asBoundedLengthArray([], 1, 5); // throws TypeError
104
136
  * ```
105
137
  *
@@ -113,5 +145,33 @@ export declare const asMaxLengthArray: <Xs extends readonly unknown[], MaxLength
113
145
  * `BoundedLengthArray<MinLength, MaxLength, Xs[number]> & Xs`.
114
146
  * @throws {TypeError} If `xs.length < minLength || xs.length > maxLength`.
115
147
  */
116
- export declare const asBoundedLengthArray: <Xs extends readonly unknown[], MinLength extends SupportedLength, MaxLength extends SupportedLength>(xs: Xs, minLength: MinLength, maxLength: MaxLength) => BoundedLengthArray<MinLength, MaxLength, Xs[number]> & Xs;
148
+ export declare function asBoundedLengthArray<Xs extends readonly unknown[], MinLength extends SupportedLength, MaxLength extends SupportedLength>(xs: Xs, minLength: MinLength, maxLength: MaxLength): BoundedLengthArray<MinLength, MaxLength, Xs[number]> & Xs;
149
+ export declare function asBoundedLengthArray<MinLength extends SupportedLength, MaxLength extends SupportedLength>(minLength: MinLength, maxLength: MaxLength): <Xs extends readonly unknown[]>(xs: Xs) => BoundedLengthArray<MinLength, MaxLength, Xs[number]> & Xs;
150
+ /**
151
+ * Casts an array to `NonEmptyArray<E>` after checking that it has at least one
152
+ * element.
153
+ *
154
+ * `NonEmptyArray<E>` is an alias of `MinLengthArray<1, E>`, so this is the
155
+ * length-1 specialization of {@link asMinLengthArray}. Use this instead of
156
+ * writing `xs as unknown as NonEmptyArray<E>`: the length is verified at
157
+ * runtime, and the original array type (e.g. tuple types) is preserved via
158
+ * intersection, so the result also benefits from the structural tuple prefix
159
+ * (`xs[0]` without `undefined` under `noUncheckedIndexedAccess`).
160
+ *
161
+ * @example
162
+ *
163
+ * ```ts
164
+ * const history = Arr.asNonEmptyArray([0, 1, 2, 3]);
165
+ *
166
+ * const first: number = history[0]; // OK — no `undefined`
167
+ *
168
+ * // Arr.asNonEmptyArray([]); // throws TypeError
169
+ * ```
170
+ *
171
+ * @template Xs - The input array type (tuple types are preserved).
172
+ * @param xs - The array to cast.
173
+ * @returns `xs` typed as `NonEmptyArray<Xs[number]> & Xs`.
174
+ * @throws {TypeError} If `xs` is empty.
175
+ */
176
+ export declare const asNonEmptyArray: <Xs extends readonly unknown[]>(xs: Xs) => NonEmptyArray<Xs[number]> & Xs;
117
177
  //# sourceMappingURL=array-utils-length-bounded-array-cast.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"array-utils-length-bounded-array-cast.d.mts","sourceRoot":"","sources":["../../../src/array/impl/array-utils-length-bounded-array-cast.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,eAAe,CAAC;AAQvB;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,kBAAkB,GAC7B,EAAE,SAAS,SAAS,OAAO,EAAE,EAC7B,MAAM,SAAS,eAAe,MAE1B,EAAE,UACE,MAAM,KACb,gBAAgB,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAQzC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,gBAAgB,GAC3B,EAAE,SAAS,SAAS,OAAO,EAAE,EAC7B,SAAS,SAAS,eAAe,MAE7B,EAAE,aACK,SAAS,KACnB,cAAc,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAQ1C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,gBAAgB,GAC3B,EAAE,SAAS,SAAS,OAAO,EAAE,EAC7B,SAAS,SAAS,eAAe,MAE7B,EAAE,aACK,SAAS,KACnB,cAAc,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAQ1C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,eAAO,MAAM,oBAAoB,GAC/B,EAAE,SAAS,SAAS,OAAO,EAAE,EAC7B,SAAS,SAAS,eAAe,EACjC,SAAS,SAAS,eAAe,MAE7B,EAAE,aACK,SAAS,aACT,SAAS,KACnB,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAQzD,CAAC"}
1
+ {"version":3,"file":"array-utils-length-bounded-array-cast.d.mts","sourceRoot":"","sources":["../../../src/array/impl/array-utils-length-bounded-array-cast.mts"],"names":[],"mappings":"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"}
@@ -1,37 +1,79 @@
1
1
  import { isBoundedLengthArray, isFixedLengthArray, isMaxLengthArray, isMinLengthArray } from './array-utils-length-bounded-array-guard.mjs';
2
2
 
3
- const asFixedLengthArray = (xs, length) => {
4
- if (!isFixedLengthArray(xs, length)) {
5
- throw new TypeError(
6
- `Expected an array of length ${length}, got an array of length ${xs.length}`
7
- );
3
+ function asFixedLengthArray(...args) {
4
+ switch (args.length) {
5
+ case 2: {
6
+ const [xs, length] = args;
7
+ if (!isFixedLengthArray(xs, length)) {
8
+ throw new TypeError(
9
+ `Expected an array of length ${length}, got an array of length ${xs.length}`
10
+ );
11
+ }
12
+ return xs;
13
+ }
14
+ case 1: {
15
+ const [length] = args;
16
+ return (xs) => asFixedLengthArray(xs, length);
17
+ }
8
18
  }
9
- return xs;
10
- };
11
- const asMinLengthArray = (xs, minLength) => {
12
- if (!isMinLengthArray(xs, minLength)) {
13
- throw new TypeError(
14
- `Expected an array of length >= ${minLength}, got an array of length ${xs.length}`
15
- );
19
+ }
20
+ function asMinLengthArray(...args) {
21
+ switch (args.length) {
22
+ case 2: {
23
+ const [xs, minLength] = args;
24
+ if (!isMinLengthArray(xs, minLength)) {
25
+ throw new TypeError(
26
+ `Expected an array of length >= ${minLength}, got an array of length ${xs.length}`
27
+ );
28
+ }
29
+ return xs;
30
+ }
31
+ case 1: {
32
+ const [minLength] = args;
33
+ return (xs) => asMinLengthArray(xs, minLength);
34
+ }
16
35
  }
17
- return xs;
18
- };
19
- const asMaxLengthArray = (xs, maxLength) => {
20
- if (!isMaxLengthArray(xs, maxLength)) {
21
- throw new TypeError(
22
- `Expected an array of length <= ${maxLength}, got an array of length ${xs.length}`
23
- );
36
+ }
37
+ function asMaxLengthArray(...args) {
38
+ switch (args.length) {
39
+ case 2: {
40
+ const [xs, maxLength] = args;
41
+ if (!isMaxLengthArray(xs, maxLength)) {
42
+ throw new TypeError(
43
+ `Expected an array of length <= ${maxLength}, got an array of length ${xs.length}`
44
+ );
45
+ }
46
+ return xs;
47
+ }
48
+ case 1: {
49
+ const [maxLength] = args;
50
+ return (xs) => asMaxLengthArray(xs, maxLength);
51
+ }
24
52
  }
25
- return xs;
26
- };
27
- const asBoundedLengthArray = (xs, minLength, maxLength) => {
28
- if (!isBoundedLengthArray(xs, minLength, maxLength)) {
29
- throw new TypeError(
30
- `Expected an array of length in [${minLength}, ${maxLength}], got an array of length ${xs.length}`
31
- );
53
+ }
54
+ function asBoundedLengthArray(...args) {
55
+ switch (args.length) {
56
+ case 3: {
57
+ const [xs, minLength, maxLength] = args;
58
+ if (!isBoundedLengthArray(xs, minLength, maxLength)) {
59
+ throw new TypeError(
60
+ `Expected an array of length in [${minLength}, ${maxLength}], got an array of length ${xs.length}`
61
+ );
62
+ }
63
+ return xs;
64
+ }
65
+ case 2: {
66
+ const [minLength, maxLength] = args;
67
+ return (xs) => asBoundedLengthArray(xs, minLength, maxLength);
68
+ }
69
+ }
70
+ }
71
+ const asNonEmptyArray = (xs) => {
72
+ if (!isMinLengthArray(xs, 1)) {
73
+ throw new TypeError("Expected a non-empty array, got an empty array");
32
74
  }
33
75
  return xs;
34
76
  };
35
77
 
36
- export { asBoundedLengthArray, asFixedLengthArray, asMaxLengthArray, asMinLengthArray };
78
+ export { asBoundedLengthArray, asFixedLengthArray, asMaxLengthArray, asMinLengthArray, asNonEmptyArray };
37
79
  //# sourceMappingURL=array-utils-length-bounded-array-cast.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"array-utils-length-bounded-array-cast.mjs","sources":["../../../src/array/impl/array-utils-length-bounded-array-cast.mts"],"sourcesContent":["import {\n type BoundedLengthArray,\n type FixedLengthArray,\n type MaxLengthArray,\n type MinLengthArray,\n type SupportedLength,\n} from 'ts-type-forge';\nimport {\n isBoundedLengthArray,\n isFixedLengthArray,\n isMaxLengthArray,\n isMinLengthArray,\n} from './array-utils-length-bounded-array-guard.mjs';\n\n/**\n * Casts an array to `FixedLengthArray<Length, E>` after checking that it has\n * exactly `length` elements.\n *\n * Use this instead of writing `xs as unknown as FixedLengthArray<N, E>`: the\n * length is verified at runtime, and the original array type (e.g. tuple\n * types) is preserved via intersection, so the result also benefits from the\n * structural tuple prefix (in-range indexed access without `undefined` under\n * `noUncheckedIndexedAccess`).\n *\n * @example\n *\n * ```ts\n * const rgb = Arr.asFixedLengthArray([255, 128, 0], 3);\n *\n * const atMost5: MaxLengthArray<5, number> = rgb; // OK (3 <= 5)\n * const red: number = rgb[0]; // OK — no `undefined`\n *\n * // Arr.asFixedLengthArray([255, 128], 3); // throws TypeError\n * ```\n *\n * @template Xs - The input array type (tuple types are preserved).\n * @template Length - The exact number of elements.\n * @param xs - The array to cast.\n * @param length - The exact number of elements.\n * @returns `xs` typed as `FixedLengthArray<Length, Xs[number]> & Xs`.\n * @throws {TypeError} If `xs.length !== length`.\n */\nexport const asFixedLengthArray = <\n Xs extends readonly unknown[],\n Length extends SupportedLength,\n>(\n xs: Xs,\n length: Length,\n): FixedLengthArray<Length, Xs[number]> & Xs => {\n if (!isFixedLengthArray(xs, length)) {\n throw new TypeError(\n `Expected an array of length ${length}, got an array of length ${xs.length}`,\n );\n }\n\n return xs;\n};\n\n/**\n * Casts an array to `MinLengthArray<MinLength, E>` after checking that it has\n * at least `minLength` elements.\n *\n * Use this instead of writing `xs as unknown as MinLengthArray<N, E>`: the\n * length is verified at runtime, and the original array type (e.g. tuple\n * types) is preserved via intersection, so the result also benefits from the\n * structural tuple prefix (indexed access below `min(N, 10)` without\n * `undefined` under `noUncheckedIndexedAccess`).\n *\n * @example\n *\n * ```ts\n * const history = Arr.asMinLengthArray([0, 1, 2, 3], 3);\n *\n * const nonEmpty: MinLengthArray<1, number> = history; // OK (3 >= 1)\n * const first: number = history[0]; // OK — no `undefined`\n *\n * // Arr.asMinLengthArray([0], 3); // throws TypeError\n * ```\n *\n * @template Xs - The input array type (tuple types are preserved).\n * @template MinLength - The minimum number of elements (inclusive).\n * @param xs - The array to cast.\n * @param minLength - The minimum number of elements (inclusive).\n * @returns `xs` typed as `MinLengthArray<MinLength, Xs[number]> & Xs`.\n * @throws {TypeError} If `xs.length < minLength`.\n */\nexport const asMinLengthArray = <\n Xs extends readonly unknown[],\n MinLength extends SupportedLength,\n>(\n xs: Xs,\n minLength: MinLength,\n): MinLengthArray<MinLength, Xs[number]> & Xs => {\n if (!isMinLengthArray(xs, minLength)) {\n throw new TypeError(\n `Expected an array of length >= ${minLength}, got an array of length ${xs.length}`,\n );\n }\n\n return xs;\n};\n\n/**\n * Casts an array to `MaxLengthArray<MaxLength, E>` after checking that it has\n * at most `maxLength` elements.\n *\n * Use this instead of writing `xs as unknown as MaxLengthArray<N, E>`: the\n * length is verified at runtime, and the original array type (e.g. tuple\n * types) is preserved via intersection.\n *\n * @example\n *\n * ```ts\n * const tags = Arr.asMaxLengthArray(['a', 'b', 'c'], 8);\n *\n * const relaxed: MaxLengthArray<16, string> = tags; // OK (8 <= 16)\n *\n * // Arr.asMaxLengthArray(['a', 'b', 'c'], 2); // throws TypeError\n * ```\n *\n * @template Xs - The input array type (tuple types are preserved).\n * @template MaxLength - The maximum number of elements (inclusive).\n * @param xs - The array to cast.\n * @param maxLength - The maximum number of elements (inclusive).\n * @returns `xs` typed as `MaxLengthArray<MaxLength, Xs[number]> & Xs`.\n * @throws {TypeError} If `xs.length > maxLength`.\n */\nexport const asMaxLengthArray = <\n Xs extends readonly unknown[],\n MaxLength extends SupportedLength,\n>(\n xs: Xs,\n maxLength: MaxLength,\n): MaxLengthArray<MaxLength, Xs[number]> & Xs => {\n if (!isMaxLengthArray(xs, maxLength)) {\n throw new TypeError(\n `Expected an array of length <= ${maxLength}, got an array of length ${xs.length}`,\n );\n }\n\n return xs;\n};\n\n/**\n * Casts an array to `BoundedLengthArray<MinLength, MaxLength, E>` after\n * checking that its length is within the inclusive range\n * `[minLength, maxLength]`.\n *\n * Use this instead of writing\n * `xs as unknown as BoundedLengthArray<Min, Max, E>`: the length is verified\n * at runtime, and the original array type (e.g. tuple types) is preserved via\n * intersection.\n *\n * @example\n *\n * ```ts\n * const selection = Arr.asBoundedLengthArray([1, 2, 3], 1, 5);\n *\n * const relaxed: BoundedLengthArray<0, 100, number> = selection; // OK\n *\n * // Arr.asBoundedLengthArray([], 1, 5); // throws TypeError\n * ```\n *\n * @template Xs - The input array type (tuple types are preserved).\n * @template MinLength - The minimum number of elements (inclusive).\n * @template MaxLength - The maximum number of elements (inclusive).\n * @param xs - The array to cast.\n * @param minLength - The minimum number of elements (inclusive).\n * @param maxLength - The maximum number of elements (inclusive).\n * @returns `xs` typed as\n * `BoundedLengthArray<MinLength, MaxLength, Xs[number]> & Xs`.\n * @throws {TypeError} If `xs.length < minLength || xs.length > maxLength`.\n */\nexport const asBoundedLengthArray = <\n Xs extends readonly unknown[],\n MinLength extends SupportedLength,\n MaxLength extends SupportedLength,\n>(\n xs: Xs,\n minLength: MinLength,\n maxLength: MaxLength,\n): BoundedLengthArray<MinLength, MaxLength, Xs[number]> & Xs => {\n if (!isBoundedLengthArray(xs, minLength, maxLength)) {\n throw new TypeError(\n `Expected an array of length in [${minLength}, ${maxLength}], got an array of length ${xs.length}`,\n );\n }\n\n return xs;\n};\n"],"names":[],"mappings":";;AA0CO,MAAM,kBAAA,GAAqB,CAIhC,EAAA,EACA,MAAA,KAC8C;AAC9C,EAAA,IAAI,CAAC,kBAAA,CAAmB,EAAA,EAAI,MAAM,CAAA,EAAG;AACnC,IAAA,MAAM,IAAI,SAAA;AAAA,MACR,CAAA,4BAAA,EAA+B,MAAM,CAAA,yBAAA,EAA4B,EAAA,CAAG,MAAM,CAAA;AAAA,KAC5E;AAAA,EACF;AAEA,EAAA,OAAO,EAAA;AACT;AA8BO,MAAM,gBAAA,GAAmB,CAI9B,EAAA,EACA,SAAA,KAC+C;AAC/C,EAAA,IAAI,CAAC,gBAAA,CAAiB,EAAA,EAAI,SAAS,CAAA,EAAG;AACpC,IAAA,MAAM,IAAI,SAAA;AAAA,MACR,CAAA,+BAAA,EAAkC,SAAS,CAAA,yBAAA,EAA4B,EAAA,CAAG,MAAM,CAAA;AAAA,KAClF;AAAA,EACF;AAEA,EAAA,OAAO,EAAA;AACT;AA2BO,MAAM,gBAAA,GAAmB,CAI9B,EAAA,EACA,SAAA,KAC+C;AAC/C,EAAA,IAAI,CAAC,gBAAA,CAAiB,EAAA,EAAI,SAAS,CAAA,EAAG;AACpC,IAAA,MAAM,IAAI,SAAA;AAAA,MACR,CAAA,+BAAA,EAAkC,SAAS,CAAA,yBAAA,EAA4B,EAAA,CAAG,MAAM,CAAA;AAAA,KAClF;AAAA,EACF;AAEA,EAAA,OAAO,EAAA;AACT;AAgCO,MAAM,oBAAA,GAAuB,CAKlC,EAAA,EACA,SAAA,EACA,SAAA,KAC8D;AAC9D,EAAA,IAAI,CAAC,oBAAA,CAAqB,EAAA,EAAI,SAAA,EAAW,SAAS,CAAA,EAAG;AACnD,IAAA,MAAM,IAAI,SAAA;AAAA,MACR,mCAAmC,SAAS,CAAA,EAAA,EAAK,SAAS,CAAA,0BAAA,EAA6B,GAAG,MAAM,CAAA;AAAA,KAClG;AAAA,EACF;AAEA,EAAA,OAAO,EAAA;AACT;;;;"}
1
+ {"version":3,"file":"array-utils-length-bounded-array-cast.mjs","sources":["../../../src/array/impl/array-utils-length-bounded-array-cast.mts"],"sourcesContent":["import {\n type BoundedLengthArray,\n type FixedLengthArray,\n type MaxLengthArray,\n type MinLengthArray,\n type NonEmptyArray,\n type SupportedLength,\n} from 'ts-type-forge';\nimport {\n isBoundedLengthArray,\n isFixedLengthArray,\n isMaxLengthArray,\n isMinLengthArray,\n} from './array-utils-length-bounded-array-guard.mjs';\n\n/**\n * Casts an array to `FixedLengthArray<Length, E>` after checking that it has\n * exactly `length` elements.\n *\n * Use this instead of writing `xs as unknown as FixedLengthArray<N, E>`: the\n * length is verified at runtime, and the original array type (e.g. tuple\n * types) is preserved via intersection, so the result also benefits from the\n * structural tuple prefix (in-range indexed access without `undefined` under\n * `noUncheckedIndexedAccess`).\n *\n * Supports a curried overload: calling it with only `length` returns a\n * function that casts an array, which is convenient for `pipe`/`map`.\n *\n * @example\n *\n * ```ts\n * const rgb = Arr.asFixedLengthArray([255, 128, 0], 3);\n *\n * const atMost5: MaxLengthArray<5, number> = rgb; // OK (3 <= 5)\n * const red: number = rgb[0]; // OK — no `undefined`\n *\n * // curried version\n * const asRgb = Arr.asFixedLengthArray(3);\n * const green = asRgb([0, 255, 0]);\n *\n * // Arr.asFixedLengthArray([255, 128], 3); // throws TypeError\n * ```\n *\n * @template Xs - The input array type (tuple types are preserved).\n * @template Length - The exact number of elements.\n * @param xs - The array to cast.\n * @param length - The exact number of elements.\n * @returns `xs` typed as `FixedLengthArray<Length, Xs[number]> & Xs`.\n * @throws {TypeError} If `xs.length !== length`.\n */\nexport function asFixedLengthArray<\n Xs extends readonly unknown[],\n Length extends SupportedLength,\n>(xs: Xs, length: Length): FixedLengthArray<Length, Xs[number]> & Xs;\n\n// Curried version\nexport function asFixedLengthArray<Length extends SupportedLength>(\n length: Length,\n): <Xs extends readonly unknown[]>(\n xs: Xs,\n) => FixedLengthArray<Length, Xs[number]> & Xs;\n\nexport function asFixedLengthArray<E>(\n ...args:\n | readonly [xs: readonly E[], length: SupportedLength]\n | readonly [length: SupportedLength]\n): readonly E[] | ((xs: readonly E[]) => readonly E[]) {\n switch (args.length) {\n case 2: {\n const [xs, length] = args;\n\n if (!isFixedLengthArray(xs, length)) {\n throw new TypeError(\n `Expected an array of length ${length}, got an array of length ${xs.length}`,\n );\n }\n\n return xs;\n }\n\n case 1: {\n const [length] = args;\n\n return (xs) => asFixedLengthArray(xs, length);\n }\n }\n}\n\n/**\n * Casts an array to `MinLengthArray<MinLength, E>` after checking that it has\n * at least `minLength` elements.\n *\n * Use this instead of writing `xs as unknown as MinLengthArray<N, E>`: the\n * length is verified at runtime, and the original array type (e.g. tuple\n * types) is preserved via intersection, so the result also benefits from the\n * structural tuple prefix (indexed access below `min(N, 10)` without\n * `undefined` under `noUncheckedIndexedAccess`).\n *\n * Supports a curried overload: calling it with only `minLength` returns a\n * function that casts an array, which is convenient for `pipe`/`map`.\n *\n * @example\n *\n * ```ts\n * const history = Arr.asMinLengthArray([0, 1, 2, 3], 3);\n *\n * const nonEmpty: MinLengthArray<1, number> = history; // OK (3 >= 1)\n * const first: number = history[0]; // OK — no `undefined`\n *\n * // curried version\n * const asHistory = Arr.asMinLengthArray(3);\n * const next = asHistory([4, 5, 6, 7]);\n *\n * // Arr.asMinLengthArray([0], 3); // throws TypeError\n * ```\n *\n * @template Xs - The input array type (tuple types are preserved).\n * @template MinLength - The minimum number of elements (inclusive).\n * @param xs - The array to cast.\n * @param minLength - The minimum number of elements (inclusive).\n * @returns `xs` typed as `MinLengthArray<MinLength, Xs[number]> & Xs`.\n * @throws {TypeError} If `xs.length < minLength`.\n */\nexport function asMinLengthArray<\n Xs extends readonly unknown[],\n MinLength extends SupportedLength,\n>(xs: Xs, minLength: MinLength): MinLengthArray<MinLength, Xs[number]> & Xs;\n\n// Curried version\nexport function asMinLengthArray<MinLength extends SupportedLength>(\n minLength: MinLength,\n): <Xs extends readonly unknown[]>(\n xs: Xs,\n) => MinLengthArray<MinLength, Xs[number]> & Xs;\n\nexport function asMinLengthArray<E>(\n ...args:\n | readonly [xs: readonly E[], minLength: SupportedLength]\n | readonly [minLength: SupportedLength]\n): readonly E[] | ((xs: readonly E[]) => readonly E[]) {\n switch (args.length) {\n case 2: {\n const [xs, minLength] = args;\n\n if (!isMinLengthArray(xs, minLength)) {\n throw new TypeError(\n `Expected an array of length >= ${minLength}, got an array of length ${xs.length}`,\n );\n }\n\n return xs;\n }\n\n case 1: {\n const [minLength] = args;\n\n return (xs) => asMinLengthArray(xs, minLength);\n }\n }\n}\n\n/**\n * Casts an array to `MaxLengthArray<MaxLength, E>` after checking that it has\n * at most `maxLength` elements.\n *\n * Use this instead of writing `xs as unknown as MaxLengthArray<N, E>`: the\n * length is verified at runtime, and the original array type (e.g. tuple\n * types) is preserved via intersection.\n *\n * Supports a curried overload: calling it with only `maxLength` returns a\n * function that casts an array, which is convenient for `pipe`/`map`.\n *\n * @example\n *\n * ```ts\n * const tags = Arr.asMaxLengthArray(['a', 'b', 'c'], 8);\n *\n * const relaxed: MaxLengthArray<16, string> = tags; // OK (8 <= 16)\n *\n * // curried version\n * const asTags = Arr.asMaxLengthArray(8);\n * const more = asTags(['d', 'e']);\n *\n * // Arr.asMaxLengthArray(['a', 'b', 'c'], 2); // throws TypeError\n * ```\n *\n * @template Xs - The input array type (tuple types are preserved).\n * @template MaxLength - The maximum number of elements (inclusive).\n * @param xs - The array to cast.\n * @param maxLength - The maximum number of elements (inclusive).\n * @returns `xs` typed as `MaxLengthArray<MaxLength, Xs[number]> & Xs`.\n * @throws {TypeError} If `xs.length > maxLength`.\n */\nexport function asMaxLengthArray<\n Xs extends readonly unknown[],\n MaxLength extends SupportedLength,\n>(xs: Xs, maxLength: MaxLength): MaxLengthArray<MaxLength, Xs[number]> & Xs;\n\n// Curried version\nexport function asMaxLengthArray<MaxLength extends SupportedLength>(\n maxLength: MaxLength,\n): <Xs extends readonly unknown[]>(\n xs: Xs,\n) => MaxLengthArray<MaxLength, Xs[number]> & Xs;\n\nexport function asMaxLengthArray<E>(\n ...args:\n | readonly [xs: readonly E[], maxLength: SupportedLength]\n | readonly [maxLength: SupportedLength]\n): readonly E[] | ((xs: readonly E[]) => readonly E[]) {\n switch (args.length) {\n case 2: {\n const [xs, maxLength] = args;\n\n if (!isMaxLengthArray(xs, maxLength)) {\n throw new TypeError(\n `Expected an array of length <= ${maxLength}, got an array of length ${xs.length}`,\n );\n }\n\n return xs;\n }\n\n case 1: {\n const [maxLength] = args;\n\n return (xs) => asMaxLengthArray(xs, maxLength);\n }\n }\n}\n\n/**\n * Casts an array to `BoundedLengthArray<MinLength, MaxLength, E>` after\n * checking that its length is within the inclusive range\n * `[minLength, maxLength]`.\n *\n * Use this instead of writing\n * `xs as unknown as BoundedLengthArray<Min, Max, E>`: the length is verified\n * at runtime, and the original array type (e.g. tuple types) is preserved via\n * intersection.\n *\n * Supports a curried overload: calling it with only `minLength` and\n * `maxLength` returns a function that casts an array, which is convenient for\n * `pipe`/`map`.\n *\n * @example\n *\n * ```ts\n * const selection = Arr.asBoundedLengthArray([1, 2, 3], 1, 5);\n *\n * const relaxed: BoundedLengthArray<0, 100, number> = selection; // OK\n *\n * // curried version\n * const asSelection = Arr.asBoundedLengthArray(1, 5);\n * const next = asSelection([4, 5]);\n *\n * // Arr.asBoundedLengthArray([], 1, 5); // throws TypeError\n * ```\n *\n * @template Xs - The input array type (tuple types are preserved).\n * @template MinLength - The minimum number of elements (inclusive).\n * @template MaxLength - The maximum number of elements (inclusive).\n * @param xs - The array to cast.\n * @param minLength - The minimum number of elements (inclusive).\n * @param maxLength - The maximum number of elements (inclusive).\n * @returns `xs` typed as\n * `BoundedLengthArray<MinLength, MaxLength, Xs[number]> & Xs`.\n * @throws {TypeError} If `xs.length < minLength || xs.length > maxLength`.\n */\nexport function asBoundedLengthArray<\n Xs extends readonly unknown[],\n MinLength extends SupportedLength,\n MaxLength extends SupportedLength,\n>(\n xs: Xs,\n minLength: MinLength,\n maxLength: MaxLength,\n): BoundedLengthArray<MinLength, MaxLength, Xs[number]> & Xs;\n\n// Curried version\nexport function asBoundedLengthArray<\n MinLength extends SupportedLength,\n MaxLength extends SupportedLength,\n>(\n minLength: MinLength,\n maxLength: MaxLength,\n): <Xs extends readonly unknown[]>(\n xs: Xs,\n) => BoundedLengthArray<MinLength, MaxLength, Xs[number]> & Xs;\n\nexport function asBoundedLengthArray<E>(\n ...args:\n | readonly [\n xs: readonly E[],\n minLength: SupportedLength,\n maxLength: SupportedLength,\n ]\n | readonly [minLength: SupportedLength, maxLength: SupportedLength]\n): readonly E[] | ((xs: readonly E[]) => readonly E[]) {\n switch (args.length) {\n case 3: {\n const [xs, minLength, maxLength] = args;\n\n if (!isBoundedLengthArray(xs, minLength, maxLength)) {\n throw new TypeError(\n `Expected an array of length in [${minLength}, ${maxLength}], got an array of length ${xs.length}`,\n );\n }\n\n return xs;\n }\n\n case 2: {\n const [minLength, maxLength] = args;\n\n return (xs) => asBoundedLengthArray(xs, minLength, maxLength);\n }\n }\n}\n\n/**\n * Casts an array to `NonEmptyArray<E>` after checking that it has at least one\n * element.\n *\n * `NonEmptyArray<E>` is an alias of `MinLengthArray<1, E>`, so this is the\n * length-1 specialization of {@link asMinLengthArray}. Use this instead of\n * writing `xs as unknown as NonEmptyArray<E>`: the length is verified at\n * runtime, and the original array type (e.g. tuple types) is preserved via\n * intersection, so the result also benefits from the structural tuple prefix\n * (`xs[0]` without `undefined` under `noUncheckedIndexedAccess`).\n *\n * @example\n *\n * ```ts\n * const history = Arr.asNonEmptyArray([0, 1, 2, 3]);\n *\n * const first: number = history[0]; // OK — no `undefined`\n *\n * // Arr.asNonEmptyArray([]); // throws TypeError\n * ```\n *\n * @template Xs - The input array type (tuple types are preserved).\n * @param xs - The array to cast.\n * @returns `xs` typed as `NonEmptyArray<Xs[number]> & Xs`.\n * @throws {TypeError} If `xs` is empty.\n */\nexport const asNonEmptyArray = <Xs extends readonly unknown[]>(\n xs: Xs,\n): NonEmptyArray<Xs[number]> & Xs => {\n if (!isMinLengthArray(xs, 1)) {\n throw new TypeError('Expected a non-empty array, got an empty array');\n }\n\n return xs;\n};\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  export { copy, create, generate, generateAsync, newArray, range, seq, zeros } from './array-utils-creation.mjs';
2
2
  export { at, first, head, last } from './array-utils-element-access.mjs';
3
3
  export { entries, indices, keys, values } from './array-utils-iterators.mjs';
4
- export { asBoundedLengthArray, asFixedLengthArray, asMaxLengthArray, asMinLengthArray } from './array-utils-length-bounded-array-cast.mjs';
4
+ export { asBoundedLengthArray, asFixedLengthArray, asMaxLengthArray, asMinLengthArray, asNonEmptyArray } from './array-utils-length-bounded-array-cast.mjs';
5
5
  export { isBoundedLengthArray, isFixedLengthArray, isMaxLengthArray, isMinLengthArray } from './array-utils-length-bounded-array-guard.mjs';
6
6
  export { set, toFilled, toInserted, toPushed, toRangeFilled, toRemoved, toUnshifted, toUpdated } from './array-utils-modification.mjs';
7
7
  export { count, countBy, foldl, foldr, join, max, maxBy, min, minBy, reduce, reduceRight, sum, sumBy } from './array-utils-reducing-value.mjs';
@@ -1,4 +1,4 @@
1
- import { type BoundedLengthString, type FixedLengthString, type MaxLengthString, type MinLengthString, type SupportedLength } from 'ts-type-forge';
1
+ import { type BoundedLengthString, type FixedLengthString, type MaxLengthString, type MinLengthString, type NonEmptyString, type SupportedLength } from 'ts-type-forge';
2
2
  /**
3
3
  * Namespace providing type guards and runtime-checked casts for the branded
4
4
  * length-constrained string types (`MinLengthString`, `MaxLengthString`,
@@ -162,6 +162,9 @@ export declare namespace Str {
162
162
  * length is verified at runtime, and the original string type (e.g. literal
163
163
  * types) is preserved via intersection.
164
164
  *
165
+ * Supports a curried overload: calling it with only `minLength` returns a
166
+ * function that casts a string, which is convenient for `pipe`/`map`.
167
+ *
165
168
  * @example
166
169
  *
167
170
  * ```ts
@@ -171,6 +174,11 @@ export declare namespace Str {
171
174
  *
172
175
  * assert.isTrue(nonEmpty.length >= 12);
173
176
  *
177
+ * // curried version
178
+ * const asPassword = Str.asMinLengthString(12);
179
+ *
180
+ * assert.strictEqual(asPassword('another-secret'), 'another-secret');
181
+ *
174
182
  * assert.throws(() => Str.asMinLengthString('short', 12)); // length 5 < 12
175
183
  * ```
176
184
  *
@@ -181,7 +189,8 @@ export declare namespace Str {
181
189
  * @returns `s` typed as `MinLengthString<MinLength> & S`.
182
190
  * @throws {TypeError} If `s.length < minLength`.
183
191
  */
184
- const asMinLengthString: <S extends string, MinLength extends SupportedLength>(s: S, minLength: MinLength) => MinLengthString<MinLength> & S;
192
+ function asMinLengthString<S extends string, MinLength extends SupportedLength>(s: S, minLength: MinLength): MinLengthString<MinLength> & S;
193
+ function asMinLengthString<MinLength extends SupportedLength>(minLength: MinLength): <S extends string>(s: S) => MinLengthString<MinLength> & S;
185
194
  /**
186
195
  * Casts a string to `MaxLengthString<MaxLength>` after checking that it has
187
196
  * at most `maxLength` characters.
@@ -190,6 +199,9 @@ export declare namespace Str {
190
199
  * length is verified at runtime, and the original string type (e.g. literal
191
200
  * types) is preserved via intersection.
192
201
  *
202
+ * Supports a curried overload: calling it with only `maxLength` returns a
203
+ * function that casts a string, which is convenient for `pipe`/`map`.
204
+ *
193
205
  * @example
194
206
  *
195
207
  * ```ts
@@ -199,6 +211,11 @@ export declare namespace Str {
199
211
  *
200
212
  * assert.isTrue(relaxed.length <= 32);
201
213
  *
214
+ * // curried version
215
+ * const asUserName = Str.asMaxLengthString(32);
216
+ *
217
+ * assert.strictEqual(asUserName('another-user'), 'another-user');
218
+ *
202
219
  * assert.throws(() => Str.asMaxLengthString('noshiro', 3)); // length 7 > 3
203
220
  * ```
204
221
  *
@@ -209,7 +226,8 @@ export declare namespace Str {
209
226
  * @returns `s` typed as `MaxLengthString<MaxLength> & S`.
210
227
  * @throws {TypeError} If `s.length > maxLength`.
211
228
  */
212
- const asMaxLengthString: <S extends string, MaxLength extends SupportedLength>(s: S, maxLength: MaxLength) => MaxLengthString<MaxLength> & S;
229
+ function asMaxLengthString<S extends string, MaxLength extends SupportedLength>(s: S, maxLength: MaxLength): MaxLengthString<MaxLength> & S;
230
+ function asMaxLengthString<MaxLength extends SupportedLength>(maxLength: MaxLength): <S extends string>(s: S) => MaxLengthString<MaxLength> & S;
213
231
  /**
214
232
  * Casts a string to `BoundedLengthString<MinLength, MaxLength>` after
215
233
  * checking that its length is within the inclusive range
@@ -219,6 +237,10 @@ export declare namespace Str {
219
237
  * the length is verified at runtime, and the original string type (e.g.
220
238
  * literal types) is preserved via intersection.
221
239
  *
240
+ * Supports a curried overload: calling it with only `minLength` and
241
+ * `maxLength` returns a function that casts a string, which is convenient for
242
+ * `pipe`/`map`.
243
+ *
222
244
  * @example
223
245
  *
224
246
  * ```ts
@@ -228,6 +250,11 @@ export declare namespace Str {
228
250
  *
229
251
  * assert.isTrue(relaxed.length >= 8 && relaxed.length <= 16);
230
252
  *
253
+ * // curried version
254
+ * const asUserId = Str.asBoundedLengthString(8, 16);
255
+ *
256
+ * assert.strictEqual(asUserId('user-87654321'), 'user-87654321');
257
+ *
231
258
  * assert.throws(() => Str.asBoundedLengthString('user', 8, 16)); // length 4 < 8
232
259
  * ```
233
260
  *
@@ -240,7 +267,8 @@ export declare namespace Str {
240
267
  * @returns `s` typed as `BoundedLengthString<MinLength, MaxLength> & S`.
241
268
  * @throws {TypeError} If `s.length < minLength` or `s.length > maxLength`.
242
269
  */
243
- const asBoundedLengthString: <S extends string, MinLength extends SupportedLength, MaxLength extends SupportedLength>(s: S, minLength: MinLength, maxLength: MaxLength) => BoundedLengthString<MinLength, MaxLength> & S;
270
+ function asBoundedLengthString<S extends string, MinLength extends SupportedLength, MaxLength extends SupportedLength>(s: S, minLength: MinLength, maxLength: MaxLength): BoundedLengthString<MinLength, MaxLength> & S;
271
+ function asBoundedLengthString<MinLength extends SupportedLength, MaxLength extends SupportedLength>(minLength: MinLength, maxLength: MaxLength): <S extends string>(s: S) => BoundedLengthString<MinLength, MaxLength> & S;
244
272
  /**
245
273
  * Casts a string to `FixedLengthString<Length>` after checking that it has
246
274
  * exactly `length` characters.
@@ -249,6 +277,9 @@ export declare namespace Str {
249
277
  * length is verified at runtime, and the original string type (e.g. literal
250
278
  * types) is preserved via intersection.
251
279
  *
280
+ * Supports a curried overload: calling it with only `length` returns a
281
+ * function that casts a string, which is convenient for `pipe`/`map`.
282
+ *
252
283
  * @example
253
284
  *
254
285
  * ```ts
@@ -258,6 +289,11 @@ export declare namespace Str {
258
289
  *
259
290
  * assert.isTrue(atMost5.length === 2);
260
291
  *
292
+ * // curried version
293
+ * const asCountryCode = Str.asFixedLengthString(2);
294
+ *
295
+ * assert.strictEqual(asCountryCode('US'), 'US');
296
+ *
261
297
  * assert.throws(() => Str.asFixedLengthString('JP', 3)); // length 2 !== 3
262
298
  * ```
263
299
  *
@@ -268,6 +304,35 @@ export declare namespace Str {
268
304
  * @returns `s` typed as `FixedLengthString<Length> & S`.
269
305
  * @throws {TypeError} If `s.length !== length`.
270
306
  */
271
- const asFixedLengthString: <S extends string, Length extends SupportedLength>(s: S, length: Length) => FixedLengthString<Length> & S;
307
+ function asFixedLengthString<S extends string, Length extends SupportedLength>(s: S, length: Length): FixedLengthString<Length> & S;
308
+ function asFixedLengthString<Length extends SupportedLength>(length: Length): <S extends string>(s: S) => FixedLengthString<Length> & S;
309
+ /**
310
+ * Casts a string to `NonEmptyString` after checking that it has at least one
311
+ * character.
312
+ *
313
+ * `NonEmptyString` is an alias of `MinLengthString<1>`, so this is the
314
+ * length-1 specialization of {@link asMinLengthString}. Use this instead of
315
+ * writing `s as unknown as NonEmptyString`: the length is verified at
316
+ * runtime, and the original string type (e.g. literal types) is preserved
317
+ * via intersection.
318
+ *
319
+ * @example
320
+ *
321
+ * ```ts
322
+ * const name = Str.asNonEmptyString('noshiro');
323
+ *
324
+ * const nonEmpty: NonEmptyString = name; // OK
325
+ *
326
+ * assert.isTrue(nonEmpty.length >= 1);
327
+ *
328
+ * assert.throws(() => Str.asNonEmptyString('')); // length 0 < 1
329
+ * ```
330
+ *
331
+ * @template S - The input string type (literal types are preserved).
332
+ * @param s - The string to cast.
333
+ * @returns `s` typed as `NonEmptyString & S`.
334
+ * @throws {TypeError} If `s` is empty.
335
+ */
336
+ const asNonEmptyString: <S extends string>(s: S) => NonEmptyString & S;
272
337
  }
273
338
  //# sourceMappingURL=str.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"str.d.mts","sourceRoot":"","sources":["../../src/string/str.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,eAAe,EACrB,MAAM,eAAe,CAAC;AAEvB;;;;;;;;GAQG;AACH,yBAAiB,GAAG,CAAC;IACnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACI,MAAM,iBAAiB,GAC5B,CAAC,SAAS,MAAM,EAChB,SAAS,SAAS,eAAe,KAE9B,CAAC,aACO,SAAS,KACnB,CAAC,IAAI,eAAe,CAAC,SAAS,CAAC,GAAG,CAA0B,CAAC;IAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAiCG;IACI,MAAM,iBAAiB,GAC5B,CAAC,SAAS,MAAM,EAChB,SAAS,SAAS,eAAe,KAE9B,CAAC,aACO,SAAS,KACnB,CAAC,IAAI,eAAe,CAAC,SAAS,CAAC,GAAG,CAA0B,CAAC;IAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqCG;IACI,MAAM,qBAAqB,GAChC,CAAC,SAAS,MAAM,EAChB,SAAS,SAAS,eAAe,EACjC,SAAS,SAAS,eAAe,KAE9B,CAAC,aACO,SAAS,aACT,SAAS,KACnB,CAAC,IAAI,mBAAmB,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG,CACJ,CAAC;IAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAkCG;IACI,MAAM,mBAAmB,GAC9B,CAAC,SAAS,MAAM,EAChB,MAAM,SAAS,eAAe,KAE3B,CAAC,UACI,MAAM,KACb,CAAC,IAAI,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAwB,CAAC;IAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACI,MAAM,iBAAiB,GAC5B,CAAC,SAAS,MAAM,EAChB,SAAS,SAAS,eAAe,KAE9B,CAAC,aACO,SAAS,KACnB,eAAe,CAAC,SAAS,CAAC,GAAG,CAQ/B,CAAC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACI,MAAM,iBAAiB,GAC5B,CAAC,SAAS,MAAM,EAChB,SAAS,SAAS,eAAe,KAE9B,CAAC,aACO,SAAS,KACnB,eAAe,CAAC,SAAS,CAAC,GAAG,CAQ/B,CAAC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACI,MAAM,qBAAqB,GAChC,CAAC,SAAS,MAAM,EAChB,SAAS,SAAS,eAAe,EACjC,SAAS,SAAS,eAAe,KAE9B,CAAC,aACO,SAAS,aACT,SAAS,KACnB,mBAAmB,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG,CAQ9C,CAAC;IAEF;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACI,MAAM,mBAAmB,GAC9B,CAAC,SAAS,MAAM,EAChB,MAAM,SAAS,eAAe,KAE3B,CAAC,UACI,MAAM,KACb,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAQ9B,CAAC;CACH"}
1
+ {"version":3,"file":"str.d.mts","sourceRoot":"","sources":["../../src/string/str.mts"],"names":[],"mappings":"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"}
@@ -4,35 +4,81 @@ var Str;
4
4
  Str2.isMaxLengthString = (s, maxLength) => s.length <= maxLength;
5
5
  Str2.isBoundedLengthString = (s, minLength, maxLength) => s.length >= minLength && s.length <= maxLength;
6
6
  Str2.isFixedLengthString = (s, length) => s.length === length;
7
- Str2.asMinLengthString = (s, minLength) => {
8
- if (!(0, Str2.isMinLengthString)(s, minLength)) {
9
- throw new TypeError(
10
- `Expected a string of length >= ${minLength}, got a string of length ${s.length}`
11
- );
7
+ function asMinLengthString(...args) {
8
+ switch (args.length) {
9
+ case 2: {
10
+ const [s, minLength] = args;
11
+ if (!(0, Str2.isMinLengthString)(s, minLength)) {
12
+ throw new TypeError(
13
+ `Expected a string of length >= ${minLength}, got a string of length ${s.length}`
14
+ );
15
+ }
16
+ return s;
17
+ }
18
+ case 1: {
19
+ const [minLength] = args;
20
+ return (s) => asMinLengthString(s, minLength);
21
+ }
12
22
  }
13
- return s;
14
- };
15
- Str2.asMaxLengthString = (s, maxLength) => {
16
- if (!(0, Str2.isMaxLengthString)(s, maxLength)) {
17
- throw new TypeError(
18
- `Expected a string of length <= ${maxLength}, got a string of length ${s.length}`
19
- );
23
+ }
24
+ Str2.asMinLengthString = asMinLengthString;
25
+ function asMaxLengthString(...args) {
26
+ switch (args.length) {
27
+ case 2: {
28
+ const [s, maxLength] = args;
29
+ if (!(0, Str2.isMaxLengthString)(s, maxLength)) {
30
+ throw new TypeError(
31
+ `Expected a string of length <= ${maxLength}, got a string of length ${s.length}`
32
+ );
33
+ }
34
+ return s;
35
+ }
36
+ case 1: {
37
+ const [maxLength] = args;
38
+ return (s) => asMaxLengthString(s, maxLength);
39
+ }
20
40
  }
21
- return s;
22
- };
23
- Str2.asBoundedLengthString = (s, minLength, maxLength) => {
24
- if (!(0, Str2.isBoundedLengthString)(s, minLength, maxLength)) {
25
- throw new TypeError(
26
- `Expected a string of length in [${minLength}, ${maxLength}], got a string of length ${s.length}`
27
- );
41
+ }
42
+ Str2.asMaxLengthString = asMaxLengthString;
43
+ function asBoundedLengthString(...args) {
44
+ switch (args.length) {
45
+ case 3: {
46
+ const [s, minLength, maxLength] = args;
47
+ if (!(0, Str2.isBoundedLengthString)(s, minLength, maxLength)) {
48
+ throw new TypeError(
49
+ `Expected a string of length in [${minLength}, ${maxLength}], got a string of length ${s.length}`
50
+ );
51
+ }
52
+ return s;
53
+ }
54
+ case 2: {
55
+ const [minLength, maxLength] = args;
56
+ return (s) => asBoundedLengthString(s, minLength, maxLength);
57
+ }
28
58
  }
29
- return s;
30
- };
31
- Str2.asFixedLengthString = (s, length) => {
32
- if (!(0, Str2.isFixedLengthString)(s, length)) {
33
- throw new TypeError(
34
- `Expected a string of length ${length}, got a string of length ${s.length}`
35
- );
59
+ }
60
+ Str2.asBoundedLengthString = asBoundedLengthString;
61
+ function asFixedLengthString(...args) {
62
+ switch (args.length) {
63
+ case 2: {
64
+ const [s, length] = args;
65
+ if (!(0, Str2.isFixedLengthString)(s, length)) {
66
+ throw new TypeError(
67
+ `Expected a string of length ${length}, got a string of length ${s.length}`
68
+ );
69
+ }
70
+ return s;
71
+ }
72
+ case 1: {
73
+ const [length] = args;
74
+ return (s) => asFixedLengthString(s, length);
75
+ }
76
+ }
77
+ }
78
+ Str2.asFixedLengthString = asFixedLengthString;
79
+ Str2.asNonEmptyString = (s) => {
80
+ if (!(0, Str2.isMinLengthString)(s, 1)) {
81
+ throw new TypeError("Expected a non-empty string, got an empty string");
36
82
  }
37
83
  return s;
38
84
  };