ts-data-forge 12.2.1 → 13.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.
- package/README.md +3 -6
- package/dist/array/impl/array-utils-creation.d.mts +1 -1
- package/dist/array/impl/array-utils-creation.d.mts.map +1 -1
- package/dist/array/impl/array-utils-element-access.d.mts +1 -1
- package/dist/array/impl/array-utils-element-access.d.mts.map +1 -1
- package/dist/array/impl/array-utils-element-access.mjs +10 -13
- package/dist/array/impl/array-utils-element-access.mjs.map +1 -1
- package/dist/array/impl/array-utils-iterators.d.mts +1 -1
- package/dist/array/impl/array-utils-iterators.d.mts.map +1 -1
- package/dist/array/impl/array-utils-length-bounded-array-cast.d.mts.map +1 -1
- package/dist/array/impl/array-utils-length-bounded-array-cast.mjs +53 -53
- package/dist/array/impl/array-utils-length-bounded-array-cast.mjs.map +1 -1
- package/dist/array/impl/array-utils-modification.d.mts.map +1 -1
- package/dist/array/impl/array-utils-modification.mjs +61 -70
- package/dist/array/impl/array-utils-modification.mjs.map +1 -1
- package/dist/array/impl/array-utils-reducing-value.d.mts.map +1 -1
- package/dist/array/impl/array-utils-reducing-value.mjs +37 -47
- package/dist/array/impl/array-utils-reducing-value.mjs.map +1 -1
- package/dist/array/impl/array-utils-search.d.mts.map +1 -1
- package/dist/array/impl/array-utils-search.mjs +80 -92
- package/dist/array/impl/array-utils-search.mjs.map +1 -1
- package/dist/array/impl/array-utils-set-op.d.mts +1 -1
- package/dist/array/impl/array-utils-set-op.d.mts.map +1 -1
- package/dist/array/impl/array-utils-size.d.mts +1 -1
- package/dist/array/impl/array-utils-size.d.mts.map +1 -1
- package/dist/array/impl/array-utils-slice-clamped.mjs +9 -10
- package/dist/array/impl/array-utils-slice-clamped.mjs.map +1 -1
- package/dist/array/impl/array-utils-slicing.d.mts +1 -1
- package/dist/array/impl/array-utils-slicing.d.mts.map +1 -1
- package/dist/array/impl/array-utils-slicing.mjs +20 -32
- package/dist/array/impl/array-utils-slicing.mjs.map +1 -1
- package/dist/array/impl/array-utils-transformation.d.mts.map +1 -1
- package/dist/array/impl/array-utils-transformation.mjs +41 -52
- package/dist/array/impl/array-utils-transformation.mjs.map +1 -1
- package/dist/array/impl/array-utils-validation.d.mts +6 -4
- package/dist/array/impl/array-utils-validation.d.mts.map +1 -1
- package/dist/array/impl/array-utils-validation.mjs +10 -16
- package/dist/array/impl/array-utils-validation.mjs.map +1 -1
- package/dist/json/json.mjs +1 -1
- package/dist/json/json.mjs.map +1 -1
- package/dist/number/branded-types/finite-number.d.mts +6 -3
- package/dist/number/branded-types/finite-number.d.mts.map +1 -1
- package/dist/number/branded-types/negative-finite-number.d.mts +8 -4
- package/dist/number/branded-types/negative-finite-number.d.mts.map +1 -1
- package/dist/number/branded-types/negative-int.d.mts +2 -1
- package/dist/number/branded-types/negative-int.d.mts.map +1 -1
- package/dist/number/branded-types/negative-safe-int.d.mts +2 -1
- package/dist/number/branded-types/negative-safe-int.d.mts.map +1 -1
- package/dist/number/branded-types/non-negative-finite-number.d.mts +6 -3
- package/dist/number/branded-types/non-negative-finite-number.d.mts.map +1 -1
- package/dist/number/branded-types/non-positive-finite-number.d.mts +6 -3
- package/dist/number/branded-types/non-positive-finite-number.d.mts.map +1 -1
- package/dist/number/branded-types/non-zero-finite-number.d.mts +6 -3
- package/dist/number/branded-types/non-zero-finite-number.d.mts.map +1 -1
- package/dist/number/branded-types/positive-finite-number.d.mts +6 -3
- package/dist/number/branded-types/positive-finite-number.d.mts.map +1 -1
- package/dist/number/enum/int8.d.mts +26 -13
- package/dist/number/enum/int8.d.mts.map +1 -1
- package/dist/number/enum/uint8.d.mts +24 -12
- package/dist/number/enum/uint8.d.mts.map +1 -1
- package/dist/others/if-then.d.mts +1 -1
- package/dist/others/if-then.d.mts.map +1 -1
- package/dist/string/str.d.mts.map +1 -1
- package/dist/string/str.mjs +52 -52
- package/dist/string/str.mjs.map +1 -1
- package/package.json +8 -4
- package/src/array/impl/array-utils-element-access.mts +15 -16
- package/src/array/impl/array-utils-length-bounded-array-cast.mts +73 -60
- package/src/array/impl/array-utils-modification.mts +96 -94
- package/src/array/impl/array-utils-reducing-value.mts +68 -57
- package/src/array/impl/array-utils-search.mts +146 -148
- package/src/array/impl/array-utils-slice-clamped.mts +16 -14
- package/src/array/impl/array-utils-slicing.mts +37 -40
- package/src/array/impl/array-utils-transformation.mts +64 -62
- package/src/array/impl/array-utils-transformation.test.mts +1 -1
- package/src/array/impl/array-utils-validation.mts +29 -27
- package/src/collections/iset.test.mts +2 -2
- package/src/functional/pipe.test.mts +1 -1
- package/src/json/json.mts +1 -1
- package/src/string/str.mts +74 -61
package/dist/string/str.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"str.mjs","sources":["../../src/string/str.mts"],"sourcesContent":["import {\n type BoundedLengthString,\n type FixedLengthString,\n type MaxLengthString,\n type MinLengthString,\n type NonEmptyString,\n type SupportedLength,\n} from 'ts-type-forge';\n\n/**\n * Namespace providing type guards and runtime-checked casts for the branded\n * length-constrained string types (`MinLengthString`, `MaxLengthString`,\n * `BoundedLengthString`, `FixedLengthString`).\n *\n * Lengths are measured in UTF-16 code units (the same unit as\n * `String.prototype.length`), so characters outside the Basic Multilingual\n * Plane (e.g. emoji) count as 2.\n */\nexport namespace Str {\n /**\n * Type guard that checks if a string has at least `minLength` characters.\n *\n * **Type Narrowing Behavior:**\n *\n * - Narrows the input to `MinLengthString<MinLength>` while preserving the\n * original string type (e.g. literal types) via intersection.\n * - The result participates in the length-constraint subtyping relation: for\n * example, a value narrowed to `MinLengthString<3>` is assignable to\n * `MinLengthString<1>` (= `NonEmptyString`).\n *\n * @example\n *\n * ```ts\n * const input: string = 'very-secret-password';\n *\n * assert.isTrue(Str.isMinLengthString(input, 12));\n *\n * assert.isFalse(Str.isMinLengthString('short', 12));\n *\n * if (Str.isMinLengthString(input, 12)) {\n * const nonEmpty: NonEmptyString = input; // OK (12 >= 1)\n *\n * assert.isTrue(nonEmpty.length >= 12);\n * }\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template MinLength - The minimum number of characters (inclusive).\n * @param s - The string to check.\n * @param minLength - The minimum number of characters (inclusive).\n * @returns `true` if `s.length >= minLength`, `false` otherwise. When `true`,\n * TypeScript narrows `s` to `MinLengthString<MinLength> & S`.\n */\n export const isMinLengthString = <\n S extends string,\n MinLength extends SupportedLength,\n >(\n s: S,\n minLength: MinLength,\n ): s is MinLengthString<MinLength> & S => s.length >= minLength;\n\n /**\n * Type guard that checks if a string has at most `maxLength` characters.\n *\n * **Type Narrowing Behavior:**\n *\n * - Narrows the input to `MaxLengthString<MaxLength>` while preserving the\n * original string type (e.g. literal types) via intersection.\n * - The result participates in the length-constraint subtyping relation: for\n * example, a value narrowed to `MaxLengthString<16>` is assignable to\n * `MaxLengthString<32>`.\n *\n * @example\n *\n * ```ts\n * const input: string = 'noshiro';\n *\n * assert.isTrue(Str.isMaxLengthString(input, 32));\n *\n * assert.isFalse(Str.isMaxLengthString(input, 3));\n *\n * if (Str.isMaxLengthString(input, 32)) {\n * const relaxed: MaxLengthString<64> = input; // OK (32 <= 64)\n *\n * assert.isTrue(relaxed.length <= 32);\n * }\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template MaxLength - The maximum number of characters (inclusive).\n * @param s - The string to check.\n * @param maxLength - The maximum number of characters (inclusive).\n * @returns `true` if `s.length <= maxLength`, `false` otherwise. When `true`,\n * TypeScript narrows `s` to `MaxLengthString<MaxLength> & S`.\n */\n export const isMaxLengthString = <\n S extends string,\n MaxLength extends SupportedLength,\n >(\n s: S,\n maxLength: MaxLength,\n ): s is MaxLengthString<MaxLength> & S => s.length <= maxLength;\n\n /**\n * Type guard that checks if a string's length is within the inclusive range\n * `[minLength, maxLength]`.\n *\n * **Type Narrowing Behavior:**\n *\n * - Narrows the input to `BoundedLengthString<MinLength, MaxLength>` while\n * preserving the original string type (e.g. literal types) via intersection.\n * - Since `BoundedLengthString` is the intersection of `MinLengthString` and\n * `MaxLengthString`, the narrowed value is assignable to both, and both\n * bounds can be weakened independently.\n *\n * @example\n *\n * ```ts\n * const input: string = 'user-12345678';\n *\n * assert.isTrue(Str.isBoundedLengthString(input, 8, 16));\n *\n * assert.isFalse(Str.isBoundedLengthString('user', 8, 16));\n *\n * if (Str.isBoundedLengthString(input, 8, 16)) {\n * const userId: BoundedLengthString<1, 255> = input; // OK ([8, 16] ⊆ [1, 255])\n *\n * assert.isTrue(userId.length >= 8 && userId.length <= 16);\n * }\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template MinLength - The minimum number of characters (inclusive).\n * @template MaxLength - The maximum number of characters (inclusive).\n * @param s - The string to check.\n * @param minLength - The minimum number of characters (inclusive).\n * @param maxLength - The maximum number of characters (inclusive).\n * @returns `true` if `minLength <= s.length && s.length <= maxLength`, `false`\n * otherwise. When `true`, TypeScript narrows `s` to\n * `BoundedLengthString<MinLength, MaxLength> & S`.\n */\n export const isBoundedLengthString = <\n S extends string,\n MinLength extends SupportedLength,\n MaxLength extends SupportedLength,\n >(\n s: S,\n minLength: MinLength,\n maxLength: MaxLength,\n ): s is BoundedLengthString<MinLength, MaxLength> & S =>\n s.length >= minLength && s.length <= maxLength;\n\n /**\n * Type guard that checks if a string has exactly `length` characters.\n *\n * **Type Narrowing Behavior:**\n *\n * - Narrows the input to `FixedLengthString<Length>` while preserving the\n * original string type (e.g. literal types) via intersection.\n * - Since `FixedLengthString<Length>` is defined as\n * `BoundedLengthString<Length, Length>`, the narrowed value is assignable to\n * any `MinLengthString<N>` with `N <= Length` and any `MaxLengthString<N>`\n * with `N >= Length`.\n *\n * @example\n *\n * ```ts\n * const input: string = 'JP';\n *\n * assert.isTrue(Str.isFixedLengthString(input, 2));\n *\n * assert.isFalse(Str.isFixedLengthString(input, 3));\n *\n * if (Str.isFixedLengthString(input, 2)) {\n * const atMost5: MaxLengthString<5> = input; // OK (2 <= 5)\n *\n * assert.isTrue(atMost5.length === 2);\n * }\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template Length - The exact number of characters.\n * @param s - The string to check.\n * @param length - The exact number of characters.\n * @returns `true` if `s.length === length`, `false` otherwise. When `true`,\n * TypeScript narrows `s` to `FixedLengthString<Length> & S`.\n */\n export const isFixedLengthString = <\n S extends string,\n Length extends SupportedLength,\n >(\n s: S,\n length: Length,\n ): s is FixedLengthString<Length> & S => s.length === length;\n\n /**\n * Casts a string to `MinLengthString<MinLength>` after checking that it has\n * at least `minLength` characters.\n *\n * Use this instead of writing `s as unknown as MinLengthString<N>`: the\n * length is verified at runtime, and the original string type (e.g. literal\n * types) is preserved via intersection.\n *\n * Supports a curried overload: calling it with only `minLength` returns a\n * function that casts a string, which is convenient for `pipe`/`map`.\n *\n * @example\n *\n * ```ts\n * const password = Str.asMinLengthString('very-secret-password', 12);\n *\n * const nonEmpty: NonEmptyString = password; // OK (>= 1)\n *\n * assert.isTrue(nonEmpty.length >= 12);\n *\n * // curried version\n * const asPassword = Str.asMinLengthString(12);\n *\n * assert.strictEqual(asPassword('another-secret'), 'another-secret');\n *\n * assert.throws(() => Str.asMinLengthString('short', 12)); // length 5 < 12\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template MinLength - The minimum number of characters (inclusive).\n * @param s - The string to cast.\n * @param minLength - The minimum number of characters (inclusive).\n * @returns `s` typed as `MinLengthString<MinLength> & S`.\n * @throws {TypeError} If `s.length < minLength`.\n */\n export function asMinLengthString<\n S extends string,\n MinLength extends SupportedLength,\n >(s: S, minLength: MinLength): MinLengthString<MinLength> & S;\n\n // Curried version\n export function asMinLengthString<MinLength extends SupportedLength>(\n minLength: MinLength,\n ): <S extends string>(s: S) => MinLengthString<MinLength> & S;\n\n export function asMinLengthString(\n ...args:\n | readonly [s: string, minLength: SupportedLength]\n | readonly [minLength: SupportedLength]\n ): string | ((s: string) => string) {\n switch (args.length) {\n case 2: {\n const [s, minLength] = args;\n\n if (!isMinLengthString(s, minLength)) {\n throw new TypeError(\n `Expected a string of length >= ${minLength}, got a string of length ${s.length}`,\n );\n }\n\n return s;\n }\n\n case 1: {\n const [minLength] = args;\n\n return (s) => asMinLengthString(s, minLength);\n }\n }\n }\n\n /**\n * Casts a string to `MaxLengthString<MaxLength>` after checking that it has\n * at most `maxLength` characters.\n *\n * Use this instead of writing `s as unknown as MaxLengthString<N>`: the\n * length is verified at runtime, and the original string type (e.g. literal\n * types) is preserved via intersection.\n *\n * Supports a curried overload: calling it with only `maxLength` returns a\n * function that casts a string, which is convenient for `pipe`/`map`.\n *\n * @example\n *\n * ```ts\n * const userName = Str.asMaxLengthString('noshiro', 32);\n *\n * const relaxed: MaxLengthString<64> = userName; // OK (32 <= 64)\n *\n * assert.isTrue(relaxed.length <= 32);\n *\n * // curried version\n * const asUserName = Str.asMaxLengthString(32);\n *\n * assert.strictEqual(asUserName('another-user'), 'another-user');\n *\n * assert.throws(() => Str.asMaxLengthString('noshiro', 3)); // length 7 > 3\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template MaxLength - The maximum number of characters (inclusive).\n * @param s - The string to cast.\n * @param maxLength - The maximum number of characters (inclusive).\n * @returns `s` typed as `MaxLengthString<MaxLength> & S`.\n * @throws {TypeError} If `s.length > maxLength`.\n */\n export function asMaxLengthString<\n S extends string,\n MaxLength extends SupportedLength,\n >(s: S, maxLength: MaxLength): MaxLengthString<MaxLength> & S;\n\n // Curried version\n export function asMaxLengthString<MaxLength extends SupportedLength>(\n maxLength: MaxLength,\n ): <S extends string>(s: S) => MaxLengthString<MaxLength> & S;\n\n export function asMaxLengthString(\n ...args:\n | readonly [s: string, maxLength: SupportedLength]\n | readonly [maxLength: SupportedLength]\n ): string | ((s: string) => string) {\n switch (args.length) {\n case 2: {\n const [s, maxLength] = args;\n\n if (!isMaxLengthString(s, maxLength)) {\n throw new TypeError(\n `Expected a string of length <= ${maxLength}, got a string of length ${s.length}`,\n );\n }\n\n return s;\n }\n\n case 1: {\n const [maxLength] = args;\n\n return (s) => asMaxLengthString(s, maxLength);\n }\n }\n }\n\n /**\n * Casts a string to `BoundedLengthString<MinLength, MaxLength>` after\n * checking that its length is within the inclusive range\n * `[minLength, maxLength]`.\n *\n * Use this instead of writing `s as unknown as BoundedLengthString<M, N>`:\n * the length is verified at runtime, and the original string type (e.g.\n * literal types) is preserved via intersection.\n *\n * Supports a curried overload: calling it with only `minLength` and\n * `maxLength` returns a function that casts a string, which is convenient for\n * `pipe`/`map`.\n *\n * @example\n *\n * ```ts\n * const userId = Str.asBoundedLengthString('user-12345678', 8, 16);\n *\n * const relaxed: BoundedLengthString<1, 255> = userId; // OK ([8, 16] ⊆ [1, 255])\n *\n * assert.isTrue(relaxed.length >= 8 && relaxed.length <= 16);\n *\n * // curried version\n * const asUserId = Str.asBoundedLengthString(8, 16);\n *\n * assert.strictEqual(asUserId('user-87654321'), 'user-87654321');\n *\n * assert.throws(() => Str.asBoundedLengthString('user', 8, 16)); // length 4 < 8\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template MinLength - The minimum number of characters (inclusive).\n * @template MaxLength - The maximum number of characters (inclusive).\n * @param s - The string to cast.\n * @param minLength - The minimum number of characters (inclusive).\n * @param maxLength - The maximum number of characters (inclusive).\n * @returns `s` typed as `BoundedLengthString<MinLength, MaxLength> & S`.\n * @throws {TypeError} If `s.length < minLength` or `s.length > maxLength`.\n */\n export function asBoundedLengthString<\n S extends string,\n MinLength extends SupportedLength,\n MaxLength extends SupportedLength,\n >(\n s: S,\n minLength: MinLength,\n maxLength: MaxLength,\n ): BoundedLengthString<MinLength, MaxLength> & S;\n\n // Curried version\n export function asBoundedLengthString<\n MinLength extends SupportedLength,\n MaxLength extends SupportedLength,\n >(\n minLength: MinLength,\n maxLength: MaxLength,\n ): <S extends string>(s: S) => BoundedLengthString<MinLength, MaxLength> & S;\n\n export function asBoundedLengthString(\n ...args:\n | readonly [\n s: string,\n minLength: SupportedLength,\n maxLength: SupportedLength,\n ]\n | readonly [minLength: SupportedLength, maxLength: SupportedLength]\n ): string | ((s: string) => string) {\n switch (args.length) {\n case 3: {\n const [s, minLength, maxLength] = args;\n\n if (!isBoundedLengthString(s, minLength, maxLength)) {\n throw new TypeError(\n `Expected a string of length in [${minLength}, ${maxLength}], got a string of length ${s.length}`,\n );\n }\n\n return s;\n }\n\n case 2: {\n const [minLength, maxLength] = args;\n\n return (s) => asBoundedLengthString(s, minLength, maxLength);\n }\n }\n }\n\n /**\n * Casts a string to `FixedLengthString<Length>` after checking that it has\n * exactly `length` characters.\n *\n * Use this instead of writing `s as unknown as FixedLengthString<N>`: the\n * length is verified at runtime, and the original string type (e.g. literal\n * types) is preserved via intersection.\n *\n * Supports a curried overload: calling it with only `length` returns a\n * function that casts a string, which is convenient for `pipe`/`map`.\n *\n * @example\n *\n * ```ts\n * const countryCode = Str.asFixedLengthString('JP', 2);\n *\n * const atMost5: MaxLengthString<5> = countryCode; // OK (2 <= 5)\n *\n * assert.isTrue(atMost5.length === 2);\n *\n * // curried version\n * const asCountryCode = Str.asFixedLengthString(2);\n *\n * assert.strictEqual(asCountryCode('US'), 'US');\n *\n * assert.throws(() => Str.asFixedLengthString('JP', 3)); // length 2 !== 3\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template Length - The exact number of characters.\n * @param s - The string to cast.\n * @param length - The exact number of characters.\n * @returns `s` typed as `FixedLengthString<Length> & S`.\n * @throws {TypeError} If `s.length !== length`.\n */\n export function asFixedLengthString<\n S extends string,\n Length extends SupportedLength,\n >(s: S, length: Length): FixedLengthString<Length> & S;\n\n // Curried version\n export function asFixedLengthString<Length extends SupportedLength>(\n length: Length,\n ): <S extends string>(s: S) => FixedLengthString<Length> & S;\n\n export function asFixedLengthString(\n ...args:\n | readonly [s: string, length: SupportedLength]\n | readonly [length: SupportedLength]\n ): string | ((s: string) => string) {\n switch (args.length) {\n case 2: {\n const [s, length] = args;\n\n if (!isFixedLengthString(s, length)) {\n throw new TypeError(\n `Expected a string of length ${length}, got a string of length ${s.length}`,\n );\n }\n\n return s;\n }\n\n case 1: {\n const [length] = args;\n\n return (s) => asFixedLengthString(s, length);\n }\n }\n }\n\n /**\n * Casts a string to `NonEmptyString` after checking that it has at least one\n * character.\n *\n * `NonEmptyString` is an alias of `MinLengthString<1>`, so this is the\n * length-1 specialization of {@link asMinLengthString}. Use this instead of\n * writing `s as unknown as NonEmptyString`: the length is verified at\n * runtime, and the original string type (e.g. literal types) is preserved\n * via intersection.\n *\n * @example\n *\n * ```ts\n * const name = Str.asNonEmptyString('noshiro');\n *\n * const nonEmpty: NonEmptyString = name; // OK\n *\n * assert.isTrue(nonEmpty.length >= 1);\n *\n * assert.throws(() => Str.asNonEmptyString('')); // length 0 < 1\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @param s - The string to cast.\n * @returns `s` typed as `NonEmptyString & S`.\n * @throws {TypeError} If `s` is empty.\n */\n export const asNonEmptyString = <S extends string>(\n s: S,\n ): NonEmptyString & S => {\n if (!isMinLengthString(s, 1)) {\n throw new TypeError('Expected a non-empty string, got an empty string');\n }\n\n return s;\n };\n}\n"],"names":["Str"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"str.mjs","sources":["../../src/string/str.mts"],"sourcesContent":["import {\n type BoundedLengthString,\n type FixedLengthString,\n type MaxLengthString,\n type MinLengthString,\n type NonEmptyString,\n type SupportedLength,\n} from 'ts-type-forge';\n\n/**\n * Namespace providing type guards and runtime-checked casts for the branded\n * length-constrained string types (`MinLengthString`, `MaxLengthString`,\n * `BoundedLengthString`, `FixedLengthString`).\n *\n * Lengths are measured in UTF-16 code units (the same unit as\n * `String.prototype.length`), so characters outside the Basic Multilingual\n * Plane (e.g. emoji) count as 2.\n */\nexport namespace Str {\n /**\n * Type guard that checks if a string has at least `minLength` characters.\n *\n * **Type Narrowing Behavior:**\n *\n * - Narrows the input to `MinLengthString<MinLength>` while preserving the\n * original string type (e.g. literal types) via intersection.\n * - The result participates in the length-constraint subtyping relation: for\n * example, a value narrowed to `MinLengthString<3>` is assignable to\n * `MinLengthString<1>` (= `NonEmptyString`).\n *\n * @example\n *\n * ```ts\n * const input: string = 'very-secret-password';\n *\n * assert.isTrue(Str.isMinLengthString(input, 12));\n *\n * assert.isFalse(Str.isMinLengthString('short', 12));\n *\n * if (Str.isMinLengthString(input, 12)) {\n * const nonEmpty: NonEmptyString = input; // OK (12 >= 1)\n *\n * assert.isTrue(nonEmpty.length >= 12);\n * }\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template MinLength - The minimum number of characters (inclusive).\n * @param s - The string to check.\n * @param minLength - The minimum number of characters (inclusive).\n * @returns `true` if `s.length >= minLength`, `false` otherwise. When `true`,\n * TypeScript narrows `s` to `MinLengthString<MinLength> & S`.\n */\n export const isMinLengthString = <\n S extends string,\n MinLength extends SupportedLength,\n >(\n s: S,\n minLength: MinLength,\n ): s is MinLengthString<MinLength> & S => s.length >= minLength;\n\n /**\n * Type guard that checks if a string has at most `maxLength` characters.\n *\n * **Type Narrowing Behavior:**\n *\n * - Narrows the input to `MaxLengthString<MaxLength>` while preserving the\n * original string type (e.g. literal types) via intersection.\n * - The result participates in the length-constraint subtyping relation: for\n * example, a value narrowed to `MaxLengthString<16>` is assignable to\n * `MaxLengthString<32>`.\n *\n * @example\n *\n * ```ts\n * const input: string = 'noshiro';\n *\n * assert.isTrue(Str.isMaxLengthString(input, 32));\n *\n * assert.isFalse(Str.isMaxLengthString(input, 3));\n *\n * if (Str.isMaxLengthString(input, 32)) {\n * const relaxed: MaxLengthString<64> = input; // OK (32 <= 64)\n *\n * assert.isTrue(relaxed.length <= 32);\n * }\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template MaxLength - The maximum number of characters (inclusive).\n * @param s - The string to check.\n * @param maxLength - The maximum number of characters (inclusive).\n * @returns `true` if `s.length <= maxLength`, `false` otherwise. When `true`,\n * TypeScript narrows `s` to `MaxLengthString<MaxLength> & S`.\n */\n export const isMaxLengthString = <\n S extends string,\n MaxLength extends SupportedLength,\n >(\n s: S,\n maxLength: MaxLength,\n ): s is MaxLengthString<MaxLength> & S => s.length <= maxLength;\n\n /**\n * Type guard that checks if a string's length is within the inclusive range\n * `[minLength, maxLength]`.\n *\n * **Type Narrowing Behavior:**\n *\n * - Narrows the input to `BoundedLengthString<MinLength, MaxLength>` while\n * preserving the original string type (e.g. literal types) via intersection.\n * - Since `BoundedLengthString` is the intersection of `MinLengthString` and\n * `MaxLengthString`, the narrowed value is assignable to both, and both\n * bounds can be weakened independently.\n *\n * @example\n *\n * ```ts\n * const input: string = 'user-12345678';\n *\n * assert.isTrue(Str.isBoundedLengthString(input, 8, 16));\n *\n * assert.isFalse(Str.isBoundedLengthString('user', 8, 16));\n *\n * if (Str.isBoundedLengthString(input, 8, 16)) {\n * const userId: BoundedLengthString<1, 255> = input; // OK ([8, 16] ⊆ [1, 255])\n *\n * assert.isTrue(userId.length >= 8 && userId.length <= 16);\n * }\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template MinLength - The minimum number of characters (inclusive).\n * @template MaxLength - The maximum number of characters (inclusive).\n * @param s - The string to check.\n * @param minLength - The minimum number of characters (inclusive).\n * @param maxLength - The maximum number of characters (inclusive).\n * @returns `true` if `minLength <= s.length && s.length <= maxLength`, `false`\n * otherwise. When `true`, TypeScript narrows `s` to\n * `BoundedLengthString<MinLength, MaxLength> & S`.\n */\n export const isBoundedLengthString = <\n S extends string,\n MinLength extends SupportedLength,\n MaxLength extends SupportedLength,\n >(\n s: S,\n minLength: MinLength,\n maxLength: MaxLength,\n ): s is BoundedLengthString<MinLength, MaxLength> & S =>\n s.length >= minLength && s.length <= maxLength;\n\n /**\n * Type guard that checks if a string has exactly `length` characters.\n *\n * **Type Narrowing Behavior:**\n *\n * - Narrows the input to `FixedLengthString<Length>` while preserving the\n * original string type (e.g. literal types) via intersection.\n * - Since `FixedLengthString<Length>` is defined as\n * `BoundedLengthString<Length, Length>`, the narrowed value is assignable to\n * any `MinLengthString<N>` with `N <= Length` and any `MaxLengthString<N>`\n * with `N >= Length`.\n *\n * @example\n *\n * ```ts\n * const input: string = 'JP';\n *\n * assert.isTrue(Str.isFixedLengthString(input, 2));\n *\n * assert.isFalse(Str.isFixedLengthString(input, 3));\n *\n * if (Str.isFixedLengthString(input, 2)) {\n * const atMost5: MaxLengthString<5> = input; // OK (2 <= 5)\n *\n * assert.isTrue(atMost5.length === 2);\n * }\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template Length - The exact number of characters.\n * @param s - The string to check.\n * @param length - The exact number of characters.\n * @returns `true` if `s.length === length`, `false` otherwise. When `true`,\n * TypeScript narrows `s` to `FixedLengthString<Length> & S`.\n */\n export const isFixedLengthString = <\n S extends string,\n Length extends SupportedLength,\n >(\n s: S,\n length: Length,\n ): s is FixedLengthString<Length> & S => s.length === length;\n\n /**\n * Casts a string to `MinLengthString<MinLength>` after checking that it has\n * at least `minLength` characters.\n *\n * Use this instead of writing `s as unknown as MinLengthString<N>`: the\n * length is verified at runtime, and the original string type (e.g. literal\n * types) is preserved via intersection.\n *\n * Supports a curried overload: calling it with only `minLength` returns a\n * function that casts a string, which is convenient for `pipe`/`map`.\n *\n * @example\n *\n * ```ts\n * const password = Str.asMinLengthString('very-secret-password', 12);\n *\n * const nonEmpty: NonEmptyString = password; // OK (>= 1)\n *\n * assert.isTrue(nonEmpty.length >= 12);\n *\n * // curried version\n * const asPassword = Str.asMinLengthString(12);\n *\n * assert.strictEqual(asPassword('another-secret'), 'another-secret');\n *\n * assert.throws(() => Str.asMinLengthString('short', 12)); // length 5 < 12\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template MinLength - The minimum number of characters (inclusive).\n * @param s - The string to cast.\n * @param minLength - The minimum number of characters (inclusive).\n * @returns `s` typed as `MinLengthString<MinLength> & S`.\n * @throws {TypeError} If `s.length < minLength`.\n */\n export function asMinLengthString<\n S extends string,\n MinLength extends SupportedLength,\n >(s: S, minLength: MinLength): MinLengthString<MinLength> & S;\n\n // Curried version\n export function asMinLengthString<MinLength extends SupportedLength>(\n minLength: MinLength,\n ): <S extends string>(s: S) => MinLengthString<MinLength> & S;\n\n export function asMinLengthString(\n ...args:\n | readonly [s: string, minLength: SupportedLength]\n | readonly [minLength: SupportedLength]\n ): string | ((s: string) => string) {\n switch (args.length) {\n case 2:\n return asMinLengthStringImpl(...args);\n\n case 1:\n return (s) => asMinLengthStringImpl(s, ...args);\n }\n }\n\n const asMinLengthStringImpl = (\n s: string,\n minLength: SupportedLength,\n ): string => {\n const actualLength = s.length;\n\n if (!isMinLengthString(s, minLength)) {\n throw new TypeError(\n `Expected a string of length >= ${minLength}, got a string of length ${actualLength}`,\n );\n }\n\n return s;\n };\n\n /**\n * Casts a string to `MaxLengthString<MaxLength>` after checking that it has\n * at most `maxLength` characters.\n *\n * Use this instead of writing `s as unknown as MaxLengthString<N>`: the\n * length is verified at runtime, and the original string type (e.g. literal\n * types) is preserved via intersection.\n *\n * Supports a curried overload: calling it with only `maxLength` returns a\n * function that casts a string, which is convenient for `pipe`/`map`.\n *\n * @example\n *\n * ```ts\n * const userName = Str.asMaxLengthString('noshiro', 32);\n *\n * const relaxed: MaxLengthString<64> = userName; // OK (32 <= 64)\n *\n * assert.isTrue(relaxed.length <= 32);\n *\n * // curried version\n * const asUserName = Str.asMaxLengthString(32);\n *\n * assert.strictEqual(asUserName('another-user'), 'another-user');\n *\n * assert.throws(() => Str.asMaxLengthString('noshiro', 3)); // length 7 > 3\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template MaxLength - The maximum number of characters (inclusive).\n * @param s - The string to cast.\n * @param maxLength - The maximum number of characters (inclusive).\n * @returns `s` typed as `MaxLengthString<MaxLength> & S`.\n * @throws {TypeError} If `s.length > maxLength`.\n */\n export function asMaxLengthString<\n S extends string,\n MaxLength extends SupportedLength,\n >(s: S, maxLength: MaxLength): MaxLengthString<MaxLength> & S;\n\n // Curried version\n export function asMaxLengthString<MaxLength extends SupportedLength>(\n maxLength: MaxLength,\n ): <S extends string>(s: S) => MaxLengthString<MaxLength> & S;\n\n export function asMaxLengthString(\n ...args:\n | readonly [s: string, maxLength: SupportedLength]\n | readonly [maxLength: SupportedLength]\n ): string | ((s: string) => string) {\n switch (args.length) {\n case 2:\n return asMaxLengthStringImpl(...args);\n\n case 1:\n return (s) => asMaxLengthStringImpl(s, ...args);\n }\n }\n\n const asMaxLengthStringImpl = (\n s: string,\n maxLength: SupportedLength,\n ): string => {\n const actualLength = s.length;\n\n if (!isMaxLengthString(s, maxLength)) {\n throw new TypeError(\n `Expected a string of length <= ${maxLength}, got a string of length ${actualLength}`,\n );\n }\n\n return s;\n };\n\n /**\n * Casts a string to `BoundedLengthString<MinLength, MaxLength>` after\n * checking that its length is within the inclusive range\n * `[minLength, maxLength]`.\n *\n * Use this instead of writing `s as unknown as BoundedLengthString<M, N>`:\n * the length is verified at runtime, and the original string type (e.g.\n * literal types) is preserved via intersection.\n *\n * Supports a curried overload: calling it with only `minLength` and\n * `maxLength` returns a function that casts a string, which is convenient for\n * `pipe`/`map`.\n *\n * @example\n *\n * ```ts\n * const userId = Str.asBoundedLengthString('user-12345678', 8, 16);\n *\n * const relaxed: BoundedLengthString<1, 255> = userId; // OK ([8, 16] ⊆ [1, 255])\n *\n * assert.isTrue(relaxed.length >= 8 && relaxed.length <= 16);\n *\n * // curried version\n * const asUserId = Str.asBoundedLengthString(8, 16);\n *\n * assert.strictEqual(asUserId('user-87654321'), 'user-87654321');\n *\n * assert.throws(() => Str.asBoundedLengthString('user', 8, 16)); // length 4 < 8\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template MinLength - The minimum number of characters (inclusive).\n * @template MaxLength - The maximum number of characters (inclusive).\n * @param s - The string to cast.\n * @param minLength - The minimum number of characters (inclusive).\n * @param maxLength - The maximum number of characters (inclusive).\n * @returns `s` typed as `BoundedLengthString<MinLength, MaxLength> & S`.\n * @throws {TypeError} If `s.length < minLength` or `s.length > maxLength`.\n */\n export function asBoundedLengthString<\n S extends string,\n MinLength extends SupportedLength,\n MaxLength extends SupportedLength,\n >(\n s: S,\n minLength: MinLength,\n maxLength: MaxLength,\n ): BoundedLengthString<MinLength, MaxLength> & S;\n\n // Curried version\n export function asBoundedLengthString<\n MinLength extends SupportedLength,\n MaxLength extends SupportedLength,\n >(\n minLength: MinLength,\n maxLength: MaxLength,\n ): <S extends string>(s: S) => BoundedLengthString<MinLength, MaxLength> & S;\n\n export function asBoundedLengthString(\n ...args:\n | readonly [\n s: string,\n minLength: SupportedLength,\n maxLength: SupportedLength,\n ]\n | readonly [minLength: SupportedLength, maxLength: SupportedLength]\n ): string | ((s: string) => string) {\n switch (args.length) {\n case 3:\n return asBoundedLengthStringImpl(...args);\n\n case 2:\n return (s) => asBoundedLengthStringImpl(s, ...args);\n }\n }\n\n const asBoundedLengthStringImpl = (\n s: string,\n minLength: SupportedLength,\n maxLength: SupportedLength,\n ): string => {\n const actualLength = s.length;\n\n if (!isBoundedLengthString(s, minLength, maxLength)) {\n throw new TypeError(\n `Expected a string of length in [${minLength}, ${maxLength}], got a string of length ${actualLength}`,\n );\n }\n\n return s;\n };\n\n /**\n * Casts a string to `FixedLengthString<Length>` after checking that it has\n * exactly `length` characters.\n *\n * Use this instead of writing `s as unknown as FixedLengthString<N>`: the\n * length is verified at runtime, and the original string type (e.g. literal\n * types) is preserved via intersection.\n *\n * Supports a curried overload: calling it with only `length` returns a\n * function that casts a string, which is convenient for `pipe`/`map`.\n *\n * @example\n *\n * ```ts\n * const countryCode = Str.asFixedLengthString('JP', 2);\n *\n * const atMost5: MaxLengthString<5> = countryCode; // OK (2 <= 5)\n *\n * assert.isTrue(atMost5.length === 2);\n *\n * // curried version\n * const asCountryCode = Str.asFixedLengthString(2);\n *\n * assert.strictEqual(asCountryCode('US'), 'US');\n *\n * assert.throws(() => Str.asFixedLengthString('JP', 3)); // length 2 !== 3\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @template Length - The exact number of characters.\n * @param s - The string to cast.\n * @param length - The exact number of characters.\n * @returns `s` typed as `FixedLengthString<Length> & S`.\n * @throws {TypeError} If `s.length !== length`.\n */\n export function asFixedLengthString<\n S extends string,\n Length extends SupportedLength,\n >(s: S, length: Length): FixedLengthString<Length> & S;\n\n // Curried version\n export function asFixedLengthString<Length extends SupportedLength>(\n length: Length,\n ): <S extends string>(s: S) => FixedLengthString<Length> & S;\n\n export function asFixedLengthString(\n ...args:\n | readonly [s: string, length: SupportedLength]\n | readonly [length: SupportedLength]\n ): string | ((s: string) => string) {\n switch (args.length) {\n case 2:\n return asFixedLengthStringImpl(...args);\n\n case 1:\n return (s) => asFixedLengthStringImpl(s, ...args);\n }\n }\n\n const asFixedLengthStringImpl = (\n s: string,\n length: SupportedLength,\n ): string => {\n const actualLength = s.length;\n\n if (!isFixedLengthString(s, length)) {\n throw new TypeError(\n `Expected a string of length ${length}, got a string of length ${actualLength}`,\n );\n }\n\n return s;\n };\n\n /**\n * Casts a string to `NonEmptyString` after checking that it has at least one\n * character.\n *\n * `NonEmptyString` is an alias of `MinLengthString<1>`, so this is the\n * length-1 specialization of {@link asMinLengthString}. Use this instead of\n * writing `s as unknown as NonEmptyString`: the length is verified at\n * runtime, and the original string type (e.g. literal types) is preserved\n * via intersection.\n *\n * @example\n *\n * ```ts\n * const name = Str.asNonEmptyString('noshiro');\n *\n * const nonEmpty: NonEmptyString = name; // OK\n *\n * assert.isTrue(nonEmpty.length >= 1);\n *\n * assert.throws(() => Str.asNonEmptyString('')); // length 0 < 1\n * ```\n *\n * @template S - The input string type (literal types are preserved).\n * @param s - The string to cast.\n * @returns `s` typed as `NonEmptyString & S`.\n * @throws {TypeError} If `s` is empty.\n */\n export const asNonEmptyString = <S extends string>(\n s: S,\n ): NonEmptyString & S => {\n if (!isMinLengthString(s, 1)) {\n throw new TypeError('Expected a non-empty string, got an empty string');\n }\n\n return s;\n };\n}\n"],"names":["Str"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-data-forge",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "13.0.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -36,16 +36,16 @@
|
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@sindresorhus/is": "^8.1.0",
|
|
39
|
-
"ts-type-forge": "7.
|
|
39
|
+
"ts-type-forge": "~7.2.1"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@emotion/react": "11.14.0",
|
|
43
43
|
"@emotion/styled": "11.14.1",
|
|
44
44
|
"@mui/material": "9.2.0",
|
|
45
45
|
"@types/react": "19.2.17",
|
|
46
|
-
"immer": "11.1.
|
|
46
|
+
"immer": "11.1.15",
|
|
47
47
|
"react": "19.2.7",
|
|
48
|
-
"typedoc": "0.28.
|
|
48
|
+
"typedoc": "0.28.20",
|
|
49
49
|
"typedoc-github-theme": "0.4.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
@@ -55,6 +55,10 @@
|
|
|
55
55
|
"node": ">=22.22.2",
|
|
56
56
|
"pnpm": ">=9.0.0"
|
|
57
57
|
},
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public",
|
|
60
|
+
"provenance": true
|
|
61
|
+
},
|
|
58
62
|
"scripts": {
|
|
59
63
|
"build": "tsx ./scripts/cmd/build.mts",
|
|
60
64
|
"build:min": "tsx ./scripts/cmd/build.mts --skip-check",
|
|
@@ -45,26 +45,25 @@ export function at<E>(
|
|
|
45
45
|
| readonly [index: SizeType.ArgArrWithNegative]
|
|
46
46
|
): Optional<E> | ((array: readonly E[]) => Optional<E>) {
|
|
47
47
|
switch (args.length) {
|
|
48
|
-
case 2:
|
|
49
|
-
|
|
48
|
+
case 2:
|
|
49
|
+
return atImpl(...args);
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
normalizedIndex < 0 || normalizedIndex >= array.length
|
|
54
|
-
? Optional.none
|
|
55
|
-
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
56
|
-
Optional.some(array[normalizedIndex]!),
|
|
57
|
-
).value;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
case 1: {
|
|
61
|
-
const [index] = args;
|
|
62
|
-
|
|
63
|
-
return (array) => at(array, index);
|
|
64
|
-
}
|
|
51
|
+
case 1:
|
|
52
|
+
return (array) => atImpl(array, ...args);
|
|
65
53
|
}
|
|
66
54
|
}
|
|
67
55
|
|
|
56
|
+
const atImpl = <E,>(
|
|
57
|
+
array: readonly E[],
|
|
58
|
+
index: SizeType.ArgArrWithNegative,
|
|
59
|
+
): Optional<E> =>
|
|
60
|
+
pipe(index < 0 ? array.length + index : index).map((normalizedIndex) =>
|
|
61
|
+
normalizedIndex < 0 || normalizedIndex >= array.length
|
|
62
|
+
? Optional.none
|
|
63
|
+
: // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
64
|
+
Optional.some(array[normalizedIndex]!),
|
|
65
|
+
).value;
|
|
66
|
+
|
|
68
67
|
/**
|
|
69
68
|
* Returns the first element of an array as an Optional.
|
|
70
69
|
*
|
|
@@ -66,25 +66,28 @@ export function asFixedLengthArray<E>(
|
|
|
66
66
|
| readonly [length: SupportedLength]
|
|
67
67
|
): readonly E[] | ((xs: readonly E[]) => readonly E[]) {
|
|
68
68
|
switch (args.length) {
|
|
69
|
-
case 2:
|
|
70
|
-
|
|
69
|
+
case 2:
|
|
70
|
+
return asFixedLengthArrayImpl(...args);
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
return xs;
|
|
79
|
-
}
|
|
72
|
+
case 1:
|
|
73
|
+
return (xs) => asFixedLengthArrayImpl(xs, ...args);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
80
76
|
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
const asFixedLengthArrayImpl = <E,>(
|
|
78
|
+
xs: readonly E[],
|
|
79
|
+
length: SupportedLength,
|
|
80
|
+
): readonly E[] => {
|
|
81
|
+
const actualLength = xs.length;
|
|
83
82
|
|
|
84
|
-
|
|
85
|
-
|
|
83
|
+
if (!isFixedLengthArray(xs, length)) {
|
|
84
|
+
throw new TypeError(
|
|
85
|
+
`Expected an array of length ${length}, got an array of length ${actualLength}`,
|
|
86
|
+
);
|
|
86
87
|
}
|
|
87
|
-
|
|
88
|
+
|
|
89
|
+
return xs;
|
|
90
|
+
};
|
|
88
91
|
|
|
89
92
|
/**
|
|
90
93
|
* Casts an array to `MinLengthArray<MinLength, E>` after checking that it has
|
|
@@ -139,25 +142,28 @@ export function asMinLengthArray<E>(
|
|
|
139
142
|
| readonly [minLength: SupportedLength]
|
|
140
143
|
): readonly E[] | ((xs: readonly E[]) => readonly E[]) {
|
|
141
144
|
switch (args.length) {
|
|
142
|
-
case 2:
|
|
143
|
-
|
|
145
|
+
case 2:
|
|
146
|
+
return asMinLengthArrayImpl(...args);
|
|
144
147
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return xs;
|
|
152
|
-
}
|
|
148
|
+
case 1:
|
|
149
|
+
return (xs) => asMinLengthArrayImpl(xs, ...args);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
153
152
|
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
const asMinLengthArrayImpl = <E,>(
|
|
154
|
+
xs: readonly E[],
|
|
155
|
+
minLength: SupportedLength,
|
|
156
|
+
): readonly E[] => {
|
|
157
|
+
const actualLength = xs.length;
|
|
156
158
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
+
if (!isMinLengthArray(xs, minLength)) {
|
|
160
|
+
throw new TypeError(
|
|
161
|
+
`Expected an array of length >= ${minLength}, got an array of length ${actualLength}`,
|
|
162
|
+
);
|
|
159
163
|
}
|
|
160
|
-
|
|
164
|
+
|
|
165
|
+
return xs;
|
|
166
|
+
};
|
|
161
167
|
|
|
162
168
|
/**
|
|
163
169
|
* Casts an array to `MaxLengthArray<MaxLength, E>` after checking that it has
|
|
@@ -209,25 +215,28 @@ export function asMaxLengthArray<E>(
|
|
|
209
215
|
| readonly [maxLength: SupportedLength]
|
|
210
216
|
): readonly E[] | ((xs: readonly E[]) => readonly E[]) {
|
|
211
217
|
switch (args.length) {
|
|
212
|
-
case 2:
|
|
213
|
-
|
|
218
|
+
case 2:
|
|
219
|
+
return asMaxLengthArrayImpl(...args);
|
|
214
220
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return xs;
|
|
222
|
-
}
|
|
221
|
+
case 1:
|
|
222
|
+
return (xs) => asMaxLengthArrayImpl(xs, ...args);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
223
225
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
+
const asMaxLengthArrayImpl = <E,>(
|
|
227
|
+
xs: readonly E[],
|
|
228
|
+
maxLength: SupportedLength,
|
|
229
|
+
): readonly E[] => {
|
|
230
|
+
const actualLength = xs.length;
|
|
226
231
|
|
|
227
|
-
|
|
228
|
-
|
|
232
|
+
if (!isMaxLengthArray(xs, maxLength)) {
|
|
233
|
+
throw new TypeError(
|
|
234
|
+
`Expected an array of length <= ${maxLength}, got an array of length ${actualLength}`,
|
|
235
|
+
);
|
|
229
236
|
}
|
|
230
|
-
|
|
237
|
+
|
|
238
|
+
return xs;
|
|
239
|
+
};
|
|
231
240
|
|
|
232
241
|
/**
|
|
233
242
|
* Casts an array to `BoundedLengthArray<MinLength, MaxLength, E>` after
|
|
@@ -298,25 +307,29 @@ export function asBoundedLengthArray<E>(
|
|
|
298
307
|
| readonly [minLength: SupportedLength, maxLength: SupportedLength]
|
|
299
308
|
): readonly E[] | ((xs: readonly E[]) => readonly E[]) {
|
|
300
309
|
switch (args.length) {
|
|
301
|
-
case 3:
|
|
302
|
-
|
|
310
|
+
case 3:
|
|
311
|
+
return asBoundedLengthArrayImpl(...args);
|
|
303
312
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
return xs;
|
|
311
|
-
}
|
|
313
|
+
case 2:
|
|
314
|
+
return (xs) => asBoundedLengthArrayImpl(xs, ...args);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
312
317
|
|
|
313
|
-
|
|
314
|
-
|
|
318
|
+
const asBoundedLengthArrayImpl = <E,>(
|
|
319
|
+
xs: readonly E[],
|
|
320
|
+
minLength: SupportedLength,
|
|
321
|
+
maxLength: SupportedLength,
|
|
322
|
+
): readonly E[] => {
|
|
323
|
+
const actualLength = xs.length;
|
|
315
324
|
|
|
316
|
-
|
|
317
|
-
|
|
325
|
+
if (!isBoundedLengthArray(xs, minLength, maxLength)) {
|
|
326
|
+
throw new TypeError(
|
|
327
|
+
`Expected an array of length in [${minLength}, ${maxLength}], got an array of length ${actualLength}`,
|
|
328
|
+
);
|
|
318
329
|
}
|
|
319
|
-
|
|
330
|
+
|
|
331
|
+
return xs;
|
|
332
|
+
};
|
|
320
333
|
|
|
321
334
|
/**
|
|
322
335
|
* Casts an array to `NonEmptyArray<E>` after checking that it has at least one
|
|
@@ -55,20 +55,20 @@ export function set<E, const V = E>(
|
|
|
55
55
|
| readonly [index: SizeType.ArgArr, newValue: V]
|
|
56
56
|
): readonly (E | V)[] | ((array: readonly E[]) => readonly (E | V)[]) {
|
|
57
57
|
switch (args.length) {
|
|
58
|
-
case 3:
|
|
59
|
-
|
|
58
|
+
case 3:
|
|
59
|
+
return setImpl(...args);
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
case 2: {
|
|
65
|
-
const [index, newValue] = args;
|
|
66
|
-
|
|
67
|
-
return (array) => set(array, index, newValue);
|
|
68
|
-
}
|
|
61
|
+
case 2:
|
|
62
|
+
return (array) => setImpl(array, ...args);
|
|
69
63
|
}
|
|
70
64
|
}
|
|
71
65
|
|
|
66
|
+
const setImpl = <E, const V = E>(
|
|
67
|
+
array: readonly E[],
|
|
68
|
+
index: SizeType.ArgArr,
|
|
69
|
+
newValue: V,
|
|
70
|
+
): readonly (E | V)[] => (array as readonly (E | V)[]).with(index, newValue);
|
|
71
|
+
|
|
72
72
|
/**
|
|
73
73
|
* Returns a new array with an element at the specified index updated by applying a function.
|
|
74
74
|
*
|
|
@@ -124,21 +124,22 @@ export function toUpdated<E, V = E>(
|
|
|
124
124
|
| readonly [index: SizeType.ArgArr, updater: (prev: E) => V]
|
|
125
125
|
): readonly (E | V)[] | ((array: readonly E[]) => readonly (E | V)[]) {
|
|
126
126
|
switch (args.length) {
|
|
127
|
-
case 3:
|
|
128
|
-
|
|
127
|
+
case 3:
|
|
128
|
+
return toUpdatedImpl(...args);
|
|
129
129
|
|
|
130
|
-
|
|
131
|
-
return (array
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
case 2: {
|
|
135
|
-
const [index, updater] = args;
|
|
136
|
-
|
|
137
|
-
return (array) => toUpdated(array, index, updater);
|
|
138
|
-
}
|
|
130
|
+
case 2:
|
|
131
|
+
return (array) => toUpdatedImpl(array, ...args);
|
|
139
132
|
}
|
|
140
133
|
}
|
|
141
134
|
|
|
135
|
+
const toUpdatedImpl = <E, V = E>(
|
|
136
|
+
array: readonly E[],
|
|
137
|
+
index: SizeType.ArgArr,
|
|
138
|
+
updater: (prev: E) => V,
|
|
139
|
+
): readonly (E | V)[] =>
|
|
140
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
141
|
+
(array as readonly (E | V)[]).with(index, updater(array[index]!));
|
|
142
|
+
|
|
142
143
|
/**
|
|
143
144
|
* Returns a new array with a value inserted at the specified index.
|
|
144
145
|
*
|
|
@@ -187,25 +188,26 @@ export function toInserted<E, const V = E>(
|
|
|
187
188
|
| readonly [index: SizeType.ArgArrWithNegative, newValue: V]
|
|
188
189
|
): NonEmptyArray<E | V> | ((array: readonly E[]) => NonEmptyArray<E | V>) {
|
|
189
190
|
switch (args.length) {
|
|
190
|
-
case 3:
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return (array
|
|
195
|
-
index,
|
|
196
|
-
0,
|
|
197
|
-
newValue,
|
|
198
|
-
) as unknown as NonEmptyArray<E | V>;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
case 2: {
|
|
202
|
-
const [index, newValue] = args;
|
|
203
|
-
|
|
204
|
-
return (array) => toInserted(array, index, newValue);
|
|
205
|
-
}
|
|
191
|
+
case 3:
|
|
192
|
+
return toInsertedImpl(...args);
|
|
193
|
+
|
|
194
|
+
case 2:
|
|
195
|
+
return (array) => toInsertedImpl(array, ...args);
|
|
206
196
|
}
|
|
207
197
|
}
|
|
208
198
|
|
|
199
|
+
const toInsertedImpl = <E, const V = E>(
|
|
200
|
+
array: readonly E[],
|
|
201
|
+
index: SizeType.ArgArrWithNegative,
|
|
202
|
+
newValue: V,
|
|
203
|
+
): NonEmptyArray<E | V> =>
|
|
204
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
205
|
+
(array as readonly (E | V)[]).toSpliced(
|
|
206
|
+
index,
|
|
207
|
+
0,
|
|
208
|
+
newValue,
|
|
209
|
+
) as unknown as NonEmptyArray<E | V>;
|
|
210
|
+
|
|
209
211
|
type CastToNumber<T> = T extends number ? T : never;
|
|
210
212
|
|
|
211
213
|
/**
|
|
@@ -240,20 +242,19 @@ export function toRemoved<E>(
|
|
|
240
242
|
| readonly [index: SizeType.ArgArrWithNegative]
|
|
241
243
|
): readonly E[] | ((array: readonly E[]) => readonly E[]) {
|
|
242
244
|
switch (args.length) {
|
|
243
|
-
case 2:
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
return array.toSpliced(index, 1);
|
|
247
|
-
}
|
|
245
|
+
case 2:
|
|
246
|
+
return toRemovedImpl(...args);
|
|
248
247
|
|
|
249
|
-
case 1:
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
return (array) => toRemoved(array, index);
|
|
253
|
-
}
|
|
248
|
+
case 1:
|
|
249
|
+
return (array) => toRemovedImpl(array, ...args);
|
|
254
250
|
}
|
|
255
251
|
}
|
|
256
252
|
|
|
253
|
+
const toRemovedImpl = <E,>(
|
|
254
|
+
array: readonly E[],
|
|
255
|
+
index: SizeType.ArgArrWithNegative,
|
|
256
|
+
): readonly E[] => array.toSpliced(index, 1);
|
|
257
|
+
|
|
257
258
|
/**
|
|
258
259
|
* Returns a new array with a value appended to the end.
|
|
259
260
|
*
|
|
@@ -291,24 +292,21 @@ export function toPushed<const Ar extends readonly unknown[], const V>(
|
|
|
291
292
|
...args: readonly [array: Ar, newValue: V] | readonly [newValue: V]
|
|
292
293
|
): readonly [...Ar, V] | ((array: Ar) => readonly [...Ar, V]) {
|
|
293
294
|
switch (args.length) {
|
|
294
|
-
case 2:
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
298
|
-
return array.toSpliced(array.length, 0, newValue) as unknown as readonly [
|
|
299
|
-
...Ar,
|
|
300
|
-
V,
|
|
301
|
-
];
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
case 1: {
|
|
305
|
-
const [newValue] = args;
|
|
295
|
+
case 2:
|
|
296
|
+
return toPushedImpl(...args);
|
|
306
297
|
|
|
307
|
-
|
|
308
|
-
|
|
298
|
+
case 1:
|
|
299
|
+
return (array) => toPushedImpl(array, ...args);
|
|
309
300
|
}
|
|
310
301
|
}
|
|
311
302
|
|
|
303
|
+
const toPushedImpl = <const Ar extends readonly unknown[], const V>(
|
|
304
|
+
array: Ar,
|
|
305
|
+
newValue: V,
|
|
306
|
+
): readonly [...Ar, V] =>
|
|
307
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
308
|
+
array.toSpliced(array.length, 0, newValue) as unknown as readonly [...Ar, V];
|
|
309
|
+
|
|
312
310
|
/**
|
|
313
311
|
* Returns a new array with a value prepended to the beginning.
|
|
314
312
|
*
|
|
@@ -346,21 +344,21 @@ export function toUnshifted<Ar extends readonly unknown[], const V>(
|
|
|
346
344
|
...args: readonly [array: Ar, newValue: V] | readonly [newValue: V]
|
|
347
345
|
): readonly [V, ...Ar] | ((array: Ar) => readonly [V, ...Ar]) {
|
|
348
346
|
switch (args.length) {
|
|
349
|
-
case 2:
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
353
|
-
return array.toSpliced(0, 0, newValue) as unknown as readonly [V, ...Ar];
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
case 1: {
|
|
357
|
-
const [newValue] = args;
|
|
347
|
+
case 2:
|
|
348
|
+
return toUnshiftedImpl(...args);
|
|
358
349
|
|
|
359
|
-
|
|
360
|
-
|
|
350
|
+
case 1:
|
|
351
|
+
return (array) => toUnshiftedImpl(array, ...args);
|
|
361
352
|
}
|
|
362
353
|
}
|
|
363
354
|
|
|
355
|
+
const toUnshiftedImpl = <Ar extends readonly unknown[], const V>(
|
|
356
|
+
array: Ar,
|
|
357
|
+
newValue: V,
|
|
358
|
+
): readonly [V, ...Ar] =>
|
|
359
|
+
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
360
|
+
array.toSpliced(0, 0, newValue) as unknown as readonly [V, ...Ar];
|
|
361
|
+
|
|
364
362
|
/**
|
|
365
363
|
* Returns a new array with all elements replaced by the specified value.
|
|
366
364
|
*
|
|
@@ -402,20 +400,17 @@ export function toFilled<E>(
|
|
|
402
400
|
...args: readonly [array: readonly E[], value: E] | readonly [value: E]
|
|
403
401
|
): readonly E[] | ((array: readonly E[]) => readonly E[]) {
|
|
404
402
|
switch (args.length) {
|
|
405
|
-
case 2:
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
return create(asPositiveUint32(array.length), value);
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
case 1: {
|
|
412
|
-
const [value] = args;
|
|
403
|
+
case 2:
|
|
404
|
+
return toFilledImpl(...args);
|
|
413
405
|
|
|
414
|
-
|
|
415
|
-
|
|
406
|
+
case 1:
|
|
407
|
+
return (array) => toFilledImpl(array, ...args);
|
|
416
408
|
}
|
|
417
409
|
}
|
|
418
410
|
|
|
411
|
+
const toFilledImpl = <E,>(array: readonly E[], value: E): readonly E[] =>
|
|
412
|
+
create(asPositiveUint32(array.length), value);
|
|
413
|
+
|
|
419
414
|
/**
|
|
420
415
|
* Returns a new array with elements in the specified range replaced by the specified value.
|
|
421
416
|
*
|
|
@@ -480,20 +475,27 @@ export function toRangeFilled<E, const V>(
|
|
|
480
475
|
]
|
|
481
476
|
): readonly (E | V)[] | ((array: readonly E[]) => readonly (E | V)[]) {
|
|
482
477
|
switch (args.length) {
|
|
483
|
-
case 3:
|
|
484
|
-
|
|
478
|
+
case 3:
|
|
479
|
+
return toRangeFilledImpl(...args);
|
|
485
480
|
|
|
486
|
-
|
|
481
|
+
case 2:
|
|
482
|
+
return (array) => toRangeFilledImpl(array, ...args);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
487
485
|
|
|
488
|
-
|
|
486
|
+
const toRangeFilledImpl = <E, const V>(
|
|
487
|
+
array: readonly E[],
|
|
488
|
+
value: V,
|
|
489
|
+
fillRange: readonly [
|
|
490
|
+
start: SizeType.ArgArrWithNegative,
|
|
491
|
+
end: SizeType.ArgArrWithNegative,
|
|
492
|
+
],
|
|
493
|
+
): readonly (E | V)[] => {
|
|
494
|
+
const [start, end] = fillRange;
|
|
489
495
|
|
|
490
|
-
|
|
491
|
-
}
|
|
496
|
+
const mut_cp: (E | V)[] = castMutable(copy(array));
|
|
492
497
|
|
|
493
|
-
|
|
494
|
-
const [value, fillRange] = args;
|
|
498
|
+
mut_cp.fill(value, start, end);
|
|
495
499
|
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
}
|
|
499
|
-
}
|
|
500
|
+
return mut_cp;
|
|
501
|
+
};
|