ts-data-forge 9.0.1 → 10.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 +1 -1
- package/dist/array/impl/array-utils-creation.d.mts +4 -4
- package/dist/array/impl/array-utils-creation.d.mts.map +1 -1
- package/dist/array/impl/array-utils-creation.mjs.map +1 -1
- package/dist/array/impl/array-utils-modification.d.mts +7 -7
- package/dist/array/impl/array-utils-modification.d.mts.map +1 -1
- package/dist/array/impl/array-utils-modification.mjs.map +1 -1
- package/dist/array/impl/array-utils-transformation.d.mts +4 -4
- package/dist/array/impl/array-utils-transformation.d.mts.map +1 -1
- package/dist/array/impl/array-utils-transformation.mjs.map +1 -1
- package/dist/array/impl/array-utils-validation.d.mts +17 -17
- package/dist/array/impl/array-utils-validation.d.mts.map +1 -1
- package/dist/array/impl/array-utils-validation.mjs +5 -5
- package/dist/array/impl/array-utils-validation.mjs.map +1 -1
- package/dist/array/impl/index.mjs +1 -1
- package/dist/entry-point.mjs +2 -0
- package/dist/entry-point.mjs.map +1 -1
- package/dist/guard/as-length-bounded-array.d.mts +117 -0
- package/dist/guard/as-length-bounded-array.d.mts.map +1 -0
- package/dist/guard/as-length-bounded-array.mjs +37 -0
- package/dist/guard/as-length-bounded-array.mjs.map +1 -0
- package/dist/guard/index.d.mts +2 -0
- package/dist/guard/index.d.mts.map +1 -1
- package/dist/guard/index.mjs +2 -0
- package/dist/guard/index.mjs.map +1 -1
- package/dist/guard/is-length-bounded-array.d.mts +159 -0
- package/dist/guard/is-length-bounded-array.d.mts.map +1 -0
- package/dist/guard/is-length-bounded-array.mjs +7 -0
- package/dist/guard/is-length-bounded-array.mjs.map +1 -0
- package/dist/guard/is-length-bounded-string.d.mts +5 -6
- package/dist/guard/is-length-bounded-string.d.mts.map +1 -1
- package/dist/guard/is-length-bounded-string.mjs.map +1 -1
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
- package/src/array/impl/array-utils-creation.mts +3 -3
- package/src/array/impl/array-utils-modification.mts +7 -7
- package/src/array/impl/array-utils-modification.test.mts +4 -4
- package/src/array/impl/array-utils-transformation.mts +4 -4
- package/src/array/impl/array-utils-transformation.test.mts +7 -7
- package/src/array/impl/array-utils-validation.mts +24 -24
- package/src/array/impl/array-utils-validation.test.mts +94 -92
- package/src/collections/queue.test.mts +1 -1
- package/src/guard/as-length-bounded-array.mts +190 -0
- package/src/guard/as-length-bounded-array.test.mts +118 -0
- package/src/guard/index.mts +2 -0
- package/src/guard/is-length-bounded-array.mts +195 -0
- package/src/guard/is-length-bounded-array.test.mts +169 -0
- package/src/guard/is-length-bounded-string.mts +6 -6
- package/src/object/object.test.mts +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array-utils-validation.mjs","sources":["../../../src/array/impl/array-utils-validation.mts"],"sourcesContent":["import {\n type
|
|
1
|
+
{"version":3,"file":"array-utils-validation.mjs","sources":["../../../src/array/impl/array-utils-validation.mts"],"sourcesContent":["import {\n type BoolOr,\n type BoundedLengthTuple,\n type FixedLengthTuple,\n type MaxLengthTuple,\n type MinLengthTuple,\n type NonEmptyArray,\n type TypeEq,\n} from 'ts-type-forge';\nimport { asUint32, Num } from '../../number/index.mjs';\nimport { type ArrayIndex, type SizeType } from '../../types.mjs';\n\n/**\n * Type guard that checks if a value is an array.\n *\n * @example\n *\n * ```ts\n * const maybeArray: unknown = [1, 2, 3] as const;\n *\n * const maybeValue: unknown = 'Ada';\n *\n * assert.isTrue(Arr.isArray(maybeArray));\n *\n * assert.isFalse(Arr.isArray(maybeValue));\n *\n * if (Arr.isArray(maybeArray)) {\n * assert.deepStrictEqual(maybeArray, [1, 2, 3]);\n * }\n * ```\n */\nexport const isArray = <E,>(value: E): value is FilterArray<E> =>\n Array.isArray(value);\n\ntype FilterArray<T> = T extends T\n ? // eslint-disable-next-line @typescript-eslint/no-explicit-any\n BoolOr<TypeEq<T, unknown>, TypeEq<T, any>> extends true\n ? Cast<readonly unknown[], T>\n : T extends readonly unknown[]\n ? T\n : never // Exclude non-array types\n : never;\n\ntype Cast<A, B> = A extends B ? A : never;\n\n// validation\n\n/**\n * Type guard that checks if an array is empty.\n *\n * @example\n *\n * ```ts\n * const emptyNumbers: readonly number[] = [] as const;\n *\n * const words = ['Ada', 'Lovelace'] as const;\n *\n * assert.isTrue(Arr.isEmpty(emptyNumbers));\n *\n * assert.isFalse(Arr.isEmpty(words));\n *\n * if (Arr.isEmpty(emptyNumbers)) {\n * assert.deepStrictEqual(emptyNumbers, []);\n * }\n * ```\n */\nexport const isEmpty = <E,>(array: readonly E[]): array is readonly [] =>\n array.length === 0;\n\n/**\n * Type guard that checks if an array is non-empty.\n *\n * @example\n *\n * ```ts\n * const users: readonly Readonly<{ id: number }>[] = [{ id: 1 }] as const;\n *\n * const emptyUsers: readonly Readonly<{ id: number }>[] = [] as const;\n *\n * assert.isTrue(Arr.isNonEmpty(users));\n *\n * assert.isFalse(Arr.isNonEmpty(emptyUsers));\n *\n * if (Arr.isNonEmpty(users)) {\n * assert.deepStrictEqual(users[0], { id: 1 });\n * }\n * ```\n */\nexport const isNonEmpty = <E,>(\n array: readonly E[],\n): array is NonEmptyArray<E> => array.length > 0;\n\n/**\n * Checks if an array has a specific length.\n *\n * @example\n *\n * ```ts\n * const pair: readonly number[] = [1, 2] as const;\n *\n * const triple: readonly number[] = [1, 2, 3] as const;\n *\n * assert.isTrue(Arr.isFixedLengthTuple(pair, 2));\n *\n * assert.isFalse(Arr.isFixedLengthTuple(triple, 2));\n *\n * if (Arr.isFixedLengthTuple(pair, 2)) {\n * assert.deepStrictEqual(pair, [1, 2]);\n * }\n * ```\n */\nexport const isFixedLengthTuple = <E, N extends SizeType.ArgArr>(\n array: readonly E[],\n len: N,\n): array is FixedLengthTuple<N, E> => array.length === len;\n\n/**\n * Checks if an array has at least a specific length.\n *\n * @example\n *\n * ```ts\n * const queue: readonly string[] = ['task-1', 'task-2'] as const;\n *\n * const emptyQueue: readonly string[] = [] as const;\n *\n * assert.isTrue(Arr.isMinLengthTuple(queue, 1));\n *\n * assert.isFalse(Arr.isMinLengthTuple(emptyQueue, 1));\n *\n * if (Arr.isMinLengthTuple(queue, 1)) {\n * assert.isTrue(queue[0] === 'task-1');\n * }\n * ```\n */\nexport const isMinLengthTuple = <E, N extends SizeType.ArgArr>(\n array: readonly E[],\n len: N,\n): array is MinLengthTuple<N, E> => array.length >= len;\n\n/**\n * Checks if an array has at most a specific length.\n *\n * @example\n *\n * ```ts\n * const pair: readonly number[] = [1, 2] as const;\n *\n * const triple: readonly number[] = [1, 2, 3] as const;\n *\n * assert.isTrue(Arr.isMaxLengthTuple(pair, 2));\n *\n * assert.isFalse(Arr.isMaxLengthTuple(triple, 2));\n *\n * if (Arr.isMaxLengthTuple(pair, 2)) {\n * assert.isTrue(pair.length <= 2);\n * }\n * ```\n */\nexport const isMaxLengthTuple = <E, N extends SizeType.ArgArr>(\n array: readonly E[],\n len: N,\n): array is MaxLengthTuple<N, E> => array.length <= len;\n\n/**\n * Checks if an array's length is within a specific inclusive range.\n *\n * @example\n *\n * ```ts\n * const pair: readonly number[] = [1, 2] as const;\n *\n * const quad: readonly number[] = [1, 2, 3, 4] as const;\n *\n * assert.isTrue(Arr.isBoundedLengthTuple(pair, 1, 3));\n *\n * assert.isFalse(Arr.isBoundedLengthTuple(quad, 1, 3));\n *\n * if (Arr.isBoundedLengthTuple(pair, 1, 3)) {\n * assert.isTrue(pair.length >= 1 && pair.length <= 3);\n * }\n * ```\n */\nexport const isBoundedLengthTuple = <\n E,\n Min extends SizeType.ArgArr,\n Max extends SizeType.ArgArr,\n>(\n array: readonly E[],\n min: Min,\n max: Max,\n): array is BoundedLengthTuple<Min, Max, E> =>\n array.length >= min && array.length <= max;\n\n/**\n * Tests whether all elements in an array pass a test implemented by a predicate.\n *\n * @example\n *\n * ```ts\n * const numbers = [2, 4, 6] as const;\n *\n * const words = ['Ada', 'Grace'] as const;\n *\n * const allEven = Arr.every(numbers, (value) => value % 2 === 0);\n *\n * const allStartWithA = Arr.every(words, (value) => value.startsWith('A'));\n *\n * assert.isTrue(allEven);\n *\n * assert.isFalse(allStartWithA);\n * ```\n */\n// Type guard overloads - narrow the entire array type\nexport function every<E, S extends E>(\n array: readonly E[],\n predicate: (a: E, index: SizeType.Arr) => a is S,\n): array is readonly S[];\n\nexport function every<E, S extends E>(\n predicate: (a: E, index: SizeType.Arr) => a is S,\n): (array: readonly E[]) => array is readonly S[];\n\n// Regular boolean predicate overloads\nexport function every<const Ar extends readonly unknown[]>(\n array: Ar,\n predicate: (a: Ar[number], index: ArrayIndex<Ar>) => boolean,\n): boolean;\n\nexport function every<E>(\n predicate: (a: E, index: SizeType.Arr) => boolean,\n): (array: readonly E[]) => boolean;\n\nexport function every<E>(\n ...args:\n | readonly [\n array: readonly E[],\n predicate: (a: E, index: SizeType.Arr) => boolean,\n ]\n | readonly [predicate: (a: E, index: SizeType.Arr) => boolean]\n): boolean | ((array: readonly E[]) => boolean) {\n switch (args.length) {\n case 2: {\n const [array, predicate] = args;\n\n return array.every((a, i) => predicate(a, asUint32(i)));\n }\n\n case 1: {\n const [predicate] = args;\n\n return (array) => every(array, predicate);\n }\n }\n}\n\n/**\n * Tests whether at least one element in an array passes a test implemented by a predicate.\n *\n * @example\n *\n * ```ts\n * const numbers = [1, 3, 5] as const;\n *\n * const words = ['Ada', 'Grace'] as const;\n *\n * const hasEven = Arr.some(numbers, (value) => value % 2 === 0);\n *\n * const hasShortName = Arr.some(words, (value) => value.length <= 3);\n *\n * assert.isFalse(hasEven);\n *\n * assert.isTrue(hasShortName);\n * ```\n */\nexport function some<const Ar extends readonly unknown[]>(\n array: Ar,\n predicate: (a: Ar[number], index: ArrayIndex<Ar>) => boolean,\n): boolean;\n\nexport function some<E>(\n predicate: (a: E, index: SizeType.Arr) => boolean,\n): (array: readonly E[]) => boolean;\n\nexport function some<E>(\n ...args:\n | readonly [\n array: readonly E[],\n predicate: (a: E, index: SizeType.Arr) => boolean,\n ]\n | readonly [predicate: (a: E, index: SizeType.Arr) => boolean]\n): boolean | ((array: readonly E[]) => boolean) {\n switch (args.length) {\n case 2: {\n const [array, predicate] = args;\n\n return array.some((a, i) => predicate(a, asUint32(i)));\n }\n\n case 1: {\n const [predicate] = args;\n\n return (array) => some(array, predicate);\n }\n }\n}\n\n/**\n * Checks if an index is within the valid range of an array.\n *\n * @example\n *\n * ```ts\n * const items = ['Ada', 'Grace', 'Katherine'] as const;\n *\n * assert.isTrue(Arr.indexIsInRange(items, 1));\n *\n * assert.isFalse(Arr.indexIsInRange(items, 3));\n *\n * if (Arr.indexIsInRange(items, 2)) {\n * assert.isTrue(items[2] === 'Katherine');\n * }\n * ```\n */\nexport const indexIsInRange = <E,>(\n array: readonly E[],\n index: SizeType.ArgArr,\n): boolean => Num.isInRange(0, array.length)(index);\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BO,MAAM,OAAA,GAAU,CAAK,KAAA,KAC1B,KAAA,CAAM,QAAQ,KAAK;AAkCd,MAAM,OAAA,GAAU,CAAK,KAAA,KAC1B,KAAA,CAAM,MAAA,KAAW;AAqBZ,MAAM,UAAA,GAAa,CACxB,KAAA,KAC8B,KAAA,CAAM,MAAA,GAAS;AAqBxC,MAAM,kBAAA,GAAqB,CAChC,KAAA,EACA,GAAA,KACoC,MAAM,MAAA,KAAW;AAqBhD,MAAM,gBAAA,GAAmB,CAC9B,KAAA,EACA,GAAA,KACkC,MAAM,MAAA,IAAU;AAqB7C,MAAM,gBAAA,GAAmB,CAC9B,KAAA,EACA,GAAA,KACkC,MAAM,MAAA,IAAU;AAqB7C,MAAM,oBAAA,GAAuB,CAKlC,KAAA,EACA,GAAA,EACA,QAEA,KAAA,CAAM,MAAA,IAAU,GAAA,IAAO,KAAA,CAAM,MAAA,IAAU;AAyClC,SAAS,SACX,IAAA,EAM2C;AAC9C,EAAA,QAAQ,KAAK,MAAA;AAAQ,IACnB,KAAK,CAAA,EAAG;AACN,MAAA,MAAM,CAAC,KAAA,EAAO,SAAS,CAAA,GAAI,IAAA;AAE3B,MAAA,OAAO,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA,EAAG,CAAA,KAAM,UAAU,CAAA,EAAG,QAAA,CAAS,CAAC,CAAC,CAAC,CAAA;AAAA,IACxD;AAAA,IAEA,KAAK,CAAA,EAAG;AACN,MAAA,MAAM,CAAC,SAAS,CAAA,GAAI,IAAA;AAEpB,MAAA,OAAO,CAAC,KAAA,KAAU,KAAA,CAAM,KAAA,EAAO,SAAS,CAAA;AAAA,IAC1C;AAAA;AAEJ;AA8BO,SAAS,QACX,IAAA,EAM2C;AAC9C,EAAA,QAAQ,KAAK,MAAA;AAAQ,IACnB,KAAK,CAAA,EAAG;AACN,MAAA,MAAM,CAAC,KAAA,EAAO,SAAS,CAAA,GAAI,IAAA;AAE3B,MAAA,OAAO,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,UAAU,CAAA,EAAG,QAAA,CAAS,CAAC,CAAC,CAAC,CAAA;AAAA,IACvD;AAAA,IAEA,KAAK,CAAA,EAAG;AACN,MAAA,MAAM,CAAC,SAAS,CAAA,GAAI,IAAA;AAEpB,MAAA,OAAO,CAAC,KAAA,KAAU,IAAA,CAAK,KAAA,EAAO,SAAS,CAAA;AAAA,IACzC;AAAA;AAEJ;AAmBO,MAAM,cAAA,GAAiB,CAC5B,KAAA,EACA,KAAA,KACY,GAAA,CAAI,UAAU,CAAA,EAAG,KAAA,CAAM,MAAM,CAAA,CAAE,KAAK;;;;"}
|
|
@@ -9,5 +9,5 @@ export { length, size } from './array-utils-size.mjs';
|
|
|
9
9
|
export { sliceClamped } from './array-utils-slice-clamped.mjs';
|
|
10
10
|
export { butLast, drop, rest, skip, skipLast, tail, take, takeLast } from './array-utils-slicing.mjs';
|
|
11
11
|
export { cartesianProduct, chunk, concat, filter, filterNot, flat, flatMap, groupBy, map, partition, scan, toReversed, toSorted, toSortedBy, uniq, uniqBy, zip } from './array-utils-transformation.mjs';
|
|
12
|
-
export { every, indexIsInRange, isArray,
|
|
12
|
+
export { every, indexIsInRange, isArray, isBoundedLengthTuple, isEmpty, isFixedLengthTuple, isMaxLengthTuple, isMinLengthTuple, isNonEmpty, some } from './array-utils-validation.mjs';
|
|
13
13
|
//# sourceMappingURL=index.mjs.map
|
package/dist/entry-point.mjs
CHANGED
|
@@ -15,7 +15,9 @@ export { ISet } from './collections/iset.mjs';
|
|
|
15
15
|
export { createQueue } from './collections/queue.mjs';
|
|
16
16
|
export { createStack } from './collections/stack.mjs';
|
|
17
17
|
export { expectType } from './expect-type.mjs';
|
|
18
|
+
export { asBoundedLengthArray, asFixedLengthArray, asMaxLengthArray, asMinLengthArray } from './guard/as-length-bounded-array.mjs';
|
|
18
19
|
export { hasKey } from './guard/has-key.mjs';
|
|
20
|
+
export { isBoundedLengthArray, isFixedLengthArray, isMaxLengthArray, isMinLengthArray } from './guard/is-length-bounded-array.mjs';
|
|
19
21
|
export { isBoundedLengthString, isFixedLengthString, isMaxLengthString, isMinLengthString } from './guard/is-length-bounded-string.mjs';
|
|
20
22
|
export { isNonEmptyString } from './guard/is-non-empty-string.mjs';
|
|
21
23
|
export { isNonNullObject } from './guard/is-non-null-object.mjs';
|
package/dist/entry-point.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry-point.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"entry-point.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { type BoundedLengthArray, type FixedLengthArray, type MaxLengthArray, type MinLengthArray, type SupportedLength } from 'ts-type-forge';
|
|
2
|
+
/**
|
|
3
|
+
* Casts an array to `FixedLengthArray<Length, E>` after checking that it has
|
|
4
|
+
* exactly `length` elements.
|
|
5
|
+
*
|
|
6
|
+
* Use this instead of writing `xs as unknown as FixedLengthArray<N, E>`: the
|
|
7
|
+
* length is verified at runtime, and the original array type (e.g. tuple
|
|
8
|
+
* types) is preserved via intersection, so the result also benefits from the
|
|
9
|
+
* structural tuple prefix (in-range indexed access without `undefined` under
|
|
10
|
+
* `noUncheckedIndexedAccess`).
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* const rgb = asFixedLengthArray([255, 128, 0], 3);
|
|
16
|
+
*
|
|
17
|
+
* const atMost5: MaxLengthArray<5, number> = rgb; // OK (3 <= 5)
|
|
18
|
+
* const red: number = rgb[0]; // OK — no `undefined`
|
|
19
|
+
*
|
|
20
|
+
* // asFixedLengthArray([255, 128], 3); // throws TypeError
|
|
21
|
+
* ```
|
|
22
|
+
*
|
|
23
|
+
* @template Xs - The input array type (tuple types are preserved).
|
|
24
|
+
* @template Length - The exact number of elements.
|
|
25
|
+
* @param xs - The array to cast.
|
|
26
|
+
* @param length - The exact number of elements.
|
|
27
|
+
* @returns `xs` typed as `FixedLengthArray<Length, Xs[number]> & Xs`.
|
|
28
|
+
* @throws {TypeError} If `xs.length !== length`.
|
|
29
|
+
*/
|
|
30
|
+
export declare const asFixedLengthArray: <Xs extends readonly unknown[], Length extends SupportedLength>(xs: Xs, length: Length) => FixedLengthArray<Length, Xs[number]> & Xs;
|
|
31
|
+
/**
|
|
32
|
+
* Casts an array to `MinLengthArray<MinLength, E>` after checking that it has
|
|
33
|
+
* at least `minLength` elements.
|
|
34
|
+
*
|
|
35
|
+
* Use this instead of writing `xs as unknown as MinLengthArray<N, E>`: the
|
|
36
|
+
* length is verified at runtime, and the original array type (e.g. tuple
|
|
37
|
+
* types) is preserved via intersection, so the result also benefits from the
|
|
38
|
+
* structural tuple prefix (indexed access below `min(N, 10)` without
|
|
39
|
+
* `undefined` under `noUncheckedIndexedAccess`).
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
*
|
|
43
|
+
* ```ts
|
|
44
|
+
* const history = asMinLengthArray([0, 1, 2, 3], 3);
|
|
45
|
+
*
|
|
46
|
+
* const nonEmpty: MinLengthArray<1, number> = history; // OK (3 >= 1)
|
|
47
|
+
* const first: number = history[0]; // OK — no `undefined`
|
|
48
|
+
*
|
|
49
|
+
* // asMinLengthArray([0], 3); // throws TypeError
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @template Xs - The input array type (tuple types are preserved).
|
|
53
|
+
* @template MinLength - The minimum number of elements (inclusive).
|
|
54
|
+
* @param xs - The array to cast.
|
|
55
|
+
* @param minLength - The minimum number of elements (inclusive).
|
|
56
|
+
* @returns `xs` typed as `MinLengthArray<MinLength, Xs[number]> & Xs`.
|
|
57
|
+
* @throws {TypeError} If `xs.length < minLength`.
|
|
58
|
+
*/
|
|
59
|
+
export declare const asMinLengthArray: <Xs extends readonly unknown[], MinLength extends SupportedLength>(xs: Xs, minLength: MinLength) => MinLengthArray<MinLength, Xs[number]> & Xs;
|
|
60
|
+
/**
|
|
61
|
+
* Casts an array to `MaxLengthArray<MaxLength, E>` after checking that it has
|
|
62
|
+
* at most `maxLength` elements.
|
|
63
|
+
*
|
|
64
|
+
* Use this instead of writing `xs as unknown as MaxLengthArray<N, E>`: the
|
|
65
|
+
* length is verified at runtime, and the original array type (e.g. tuple
|
|
66
|
+
* types) is preserved via intersection.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
*
|
|
70
|
+
* ```ts
|
|
71
|
+
* const tags = asMaxLengthArray(['a', 'b', 'c'], 8);
|
|
72
|
+
*
|
|
73
|
+
* const relaxed: MaxLengthArray<16, string> = tags; // OK (8 <= 16)
|
|
74
|
+
*
|
|
75
|
+
* // asMaxLengthArray(['a', 'b', 'c'], 2); // throws TypeError
|
|
76
|
+
* ```
|
|
77
|
+
*
|
|
78
|
+
* @template Xs - The input array type (tuple types are preserved).
|
|
79
|
+
* @template MaxLength - The maximum number of elements (inclusive).
|
|
80
|
+
* @param xs - The array to cast.
|
|
81
|
+
* @param maxLength - The maximum number of elements (inclusive).
|
|
82
|
+
* @returns `xs` typed as `MaxLengthArray<MaxLength, Xs[number]> & Xs`.
|
|
83
|
+
* @throws {TypeError} If `xs.length > maxLength`.
|
|
84
|
+
*/
|
|
85
|
+
export declare const asMaxLengthArray: <Xs extends readonly unknown[], MaxLength extends SupportedLength>(xs: Xs, maxLength: MaxLength) => MaxLengthArray<MaxLength, Xs[number]> & Xs;
|
|
86
|
+
/**
|
|
87
|
+
* Casts an array to `BoundedLengthArray<MinLength, MaxLength, E>` after
|
|
88
|
+
* checking that its length is within the inclusive range
|
|
89
|
+
* `[minLength, maxLength]`.
|
|
90
|
+
*
|
|
91
|
+
* Use this instead of writing
|
|
92
|
+
* `xs as unknown as BoundedLengthArray<Min, Max, E>`: the length is verified
|
|
93
|
+
* at runtime, and the original array type (e.g. tuple types) is preserved via
|
|
94
|
+
* intersection.
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
*
|
|
98
|
+
* ```ts
|
|
99
|
+
* const selection = asBoundedLengthArray([1, 2, 3], 1, 5);
|
|
100
|
+
*
|
|
101
|
+
* const relaxed: BoundedLengthArray<0, 100, number> = selection; // OK
|
|
102
|
+
*
|
|
103
|
+
* // asBoundedLengthArray([], 1, 5); // throws TypeError
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* @template Xs - The input array type (tuple types are preserved).
|
|
107
|
+
* @template MinLength - The minimum number of elements (inclusive).
|
|
108
|
+
* @template MaxLength - The maximum number of elements (inclusive).
|
|
109
|
+
* @param xs - The array to cast.
|
|
110
|
+
* @param minLength - The minimum number of elements (inclusive).
|
|
111
|
+
* @param maxLength - The maximum number of elements (inclusive).
|
|
112
|
+
* @returns `xs` typed as
|
|
113
|
+
* `BoundedLengthArray<MinLength, MaxLength, Xs[number]> & Xs`.
|
|
114
|
+
* @throws {TypeError} If `xs.length < minLength || xs.length > maxLength`.
|
|
115
|
+
*/
|
|
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;
|
|
117
|
+
//# sourceMappingURL=as-length-bounded-array.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"as-length-bounded-array.d.mts","sourceRoot":"","sources":["../../src/guard/as-length-bounded-array.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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { isBoundedLengthArray, isFixedLengthArray, isMaxLengthArray, isMinLengthArray } from './is-length-bounded-array.mjs';
|
|
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
|
+
);
|
|
8
|
+
}
|
|
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
|
+
);
|
|
16
|
+
}
|
|
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
|
+
);
|
|
24
|
+
}
|
|
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
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return xs;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export { asBoundedLengthArray, asFixedLengthArray, asMaxLengthArray, asMinLengthArray };
|
|
37
|
+
//# sourceMappingURL=as-length-bounded-array.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"as-length-bounded-array.mjs","sources":["../../src/guard/as-length-bounded-array.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 './is-length-bounded-array.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 = 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 * // 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 = 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 * // 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 = asMaxLengthArray(['a', 'b', 'c'], 8);\n *\n * const relaxed: MaxLengthArray<16, string> = tags; // OK (8 <= 16)\n *\n * // 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 = asBoundedLengthArray([1, 2, 3], 1, 5);\n *\n * const relaxed: BoundedLengthArray<0, 100, number> = selection; // OK\n *\n * // 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;;;;"}
|
package/dist/guard/index.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/guard/index.mts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/guard/index.mts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,eAAe,CAAC;AAC9B,cAAc,+BAA+B,CAAC;AAC9C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC"}
|
package/dist/guard/index.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
export { asBoundedLengthArray, asFixedLengthArray, asMaxLengthArray, asMinLengthArray } from './as-length-bounded-array.mjs';
|
|
1
2
|
export { hasKey } from './has-key.mjs';
|
|
3
|
+
export { isBoundedLengthArray, isFixedLengthArray, isMaxLengthArray, isMinLengthArray } from './is-length-bounded-array.mjs';
|
|
2
4
|
export { isBoundedLengthString, isFixedLengthString, isMaxLengthString, isMinLengthString } from './is-length-bounded-string.mjs';
|
|
3
5
|
export { isNonEmptyString } from './is-non-empty-string.mjs';
|
|
4
6
|
export { isNonNullObject } from './is-non-null-object.mjs';
|
package/dist/guard/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { type BoundedLengthArray, type FixedLengthArray, type MaxLengthArray, type MinLengthArray, type SupportedLength } from 'ts-type-forge';
|
|
2
|
+
/**
|
|
3
|
+
* Type guard that checks if an array has at least `minLength` elements.
|
|
4
|
+
*
|
|
5
|
+
* **Type Narrowing Behavior:**
|
|
6
|
+
*
|
|
7
|
+
* - Narrows the input to `MinLengthArray<MinLength, E>` while preserving the
|
|
8
|
+
* original array type (e.g. tuple types) via intersection.
|
|
9
|
+
* - The length constraint lives only in the brand, so this stays cheap for the
|
|
10
|
+
* type checker even when the element type is large — unlike
|
|
11
|
+
* `isMinLengthTuple`, which narrows to a structural tuple type.
|
|
12
|
+
* - The result participates in the length-constraint subtyping relation: for
|
|
13
|
+
* example, a value narrowed to `MinLengthArray<3, E>` is assignable to
|
|
14
|
+
* `MinLengthArray<1, E>`.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
*
|
|
18
|
+
* ```ts
|
|
19
|
+
* const input: readonly number[] = [0, 1, 2, 3];
|
|
20
|
+
*
|
|
21
|
+
* assert.isTrue(isMinLengthArray(input, 3));
|
|
22
|
+
*
|
|
23
|
+
* assert.isFalse(isMinLengthArray([0], 3));
|
|
24
|
+
*
|
|
25
|
+
* if (isMinLengthArray(input, 3)) {
|
|
26
|
+
* const history: MinLengthArray<3, number> = input;
|
|
27
|
+
*
|
|
28
|
+
* const nonEmpty: MinLengthArray<1, number> = input; // OK (3 >= 1)
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @template Xs - The input array type (tuple types are preserved).
|
|
33
|
+
* @template MinLength - The minimum number of elements (inclusive).
|
|
34
|
+
* @param xs - The array to check.
|
|
35
|
+
* @param minLength - The minimum number of elements (inclusive).
|
|
36
|
+
* @returns `true` if `xs.length >= minLength`, `false` otherwise. When `true`,
|
|
37
|
+
* TypeScript narrows `xs` to `MinLengthArray<MinLength, Xs[number]> & Xs`.
|
|
38
|
+
*/
|
|
39
|
+
export declare const isMinLengthArray: <Xs extends readonly unknown[], MinLength extends SupportedLength>(xs: Xs, minLength: MinLength) => xs is MinLengthArray<MinLength, Xs[number]> & Xs;
|
|
40
|
+
/**
|
|
41
|
+
* Type guard that checks if an array has at most `maxLength` elements.
|
|
42
|
+
*
|
|
43
|
+
* **Type Narrowing Behavior:**
|
|
44
|
+
*
|
|
45
|
+
* - Narrows the input to `MaxLengthArray<MaxLength, E>` while preserving the
|
|
46
|
+
* original array type (e.g. tuple types) via intersection.
|
|
47
|
+
* - The length constraint lives only in the brand, so this stays cheap for the
|
|
48
|
+
* type checker even when the element type is large — unlike
|
|
49
|
+
* `isMaxLengthTuple`, which narrows to a union of tuple types.
|
|
50
|
+
* - The result participates in the length-constraint subtyping relation: for
|
|
51
|
+
* example, a value narrowed to `MaxLengthArray<8, E>` is assignable to
|
|
52
|
+
* `MaxLengthArray<16, E>`.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
*
|
|
56
|
+
* ```ts
|
|
57
|
+
* const input: readonly string[] = ['a', 'b', 'c'];
|
|
58
|
+
*
|
|
59
|
+
* assert.isTrue(isMaxLengthArray(input, 8));
|
|
60
|
+
*
|
|
61
|
+
* assert.isFalse(isMaxLengthArray(input, 2));
|
|
62
|
+
*
|
|
63
|
+
* if (isMaxLengthArray(input, 8)) {
|
|
64
|
+
* const tags: MaxLengthArray<8, string> = input;
|
|
65
|
+
*
|
|
66
|
+
* const relaxed: MaxLengthArray<16, string> = input; // OK (8 <= 16)
|
|
67
|
+
* }
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* @template Xs - The input array type (tuple types are preserved).
|
|
71
|
+
* @template MaxLength - The maximum number of elements (inclusive).
|
|
72
|
+
* @param xs - The array to check.
|
|
73
|
+
* @param maxLength - The maximum number of elements (inclusive).
|
|
74
|
+
* @returns `true` if `xs.length <= maxLength`, `false` otherwise. When `true`,
|
|
75
|
+
* TypeScript narrows `xs` to `MaxLengthArray<MaxLength, Xs[number]> & Xs`.
|
|
76
|
+
*/
|
|
77
|
+
export declare const isMaxLengthArray: <Xs extends readonly unknown[], MaxLength extends SupportedLength>(xs: Xs, maxLength: MaxLength) => xs is MaxLengthArray<MaxLength, Xs[number]> & Xs;
|
|
78
|
+
/**
|
|
79
|
+
* Type guard that checks if an array's length is within the inclusive range
|
|
80
|
+
* `[minLength, maxLength]`.
|
|
81
|
+
*
|
|
82
|
+
* **Type Narrowing Behavior:**
|
|
83
|
+
*
|
|
84
|
+
* - Narrows the input to `BoundedLengthArray<MinLength, MaxLength, E>` while
|
|
85
|
+
* preserving the original array type (e.g. tuple types) via intersection.
|
|
86
|
+
* - Since `BoundedLengthArray` is the intersection of `MinLengthArray` and
|
|
87
|
+
* `MaxLengthArray`, the narrowed value is assignable to both, and both
|
|
88
|
+
* bounds can be weakened independently.
|
|
89
|
+
* - The length constraint lives only in the brand, so this stays cheap for the
|
|
90
|
+
* type checker even when the element type is large — unlike
|
|
91
|
+
* `isBoundedLengthTuple`, which narrows to a union of tuple types.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
*
|
|
95
|
+
* ```ts
|
|
96
|
+
* const input: readonly number[] = [1, 2, 3];
|
|
97
|
+
*
|
|
98
|
+
* assert.isTrue(isBoundedLengthArray(input, 1, 5));
|
|
99
|
+
*
|
|
100
|
+
* assert.isFalse(isBoundedLengthArray([], 1, 5));
|
|
101
|
+
*
|
|
102
|
+
* if (isBoundedLengthArray(input, 1, 5)) {
|
|
103
|
+
* const selection: BoundedLengthArray<1, 5, number> = input;
|
|
104
|
+
*
|
|
105
|
+
* const relaxed: BoundedLengthArray<0, 100, number> = input; // OK ([1, 5] ⊆ [0, 100])
|
|
106
|
+
* }
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @template Xs - The input array type (tuple types are preserved).
|
|
110
|
+
* @template MinLength - The minimum number of elements (inclusive).
|
|
111
|
+
* @template MaxLength - The maximum number of elements (inclusive).
|
|
112
|
+
* @param xs - The array to check.
|
|
113
|
+
* @param minLength - The minimum number of elements (inclusive).
|
|
114
|
+
* @param maxLength - The maximum number of elements (inclusive).
|
|
115
|
+
* @returns `true` if `minLength <= xs.length && xs.length <= maxLength`,
|
|
116
|
+
* `false` otherwise. When `true`, TypeScript narrows `xs` to
|
|
117
|
+
* `BoundedLengthArray<MinLength, MaxLength, Xs[number]> & Xs`.
|
|
118
|
+
*/
|
|
119
|
+
export declare const isBoundedLengthArray: <Xs extends readonly unknown[], MinLength extends SupportedLength, MaxLength extends SupportedLength>(xs: Xs, minLength: MinLength, maxLength: MaxLength) => xs is BoundedLengthArray<MinLength, MaxLength, Xs[number]> & Xs;
|
|
120
|
+
/**
|
|
121
|
+
* Type guard that checks if an array has exactly `length` elements.
|
|
122
|
+
*
|
|
123
|
+
* **Type Narrowing Behavior:**
|
|
124
|
+
*
|
|
125
|
+
* - Narrows the input to `FixedLengthArray<Length, E>` while preserving the
|
|
126
|
+
* original array type (e.g. tuple types) via intersection.
|
|
127
|
+
* - Since `FixedLengthArray<Length, E>` is defined as
|
|
128
|
+
* `BoundedLengthArray<Length, Length, E>`, the narrowed value is assignable
|
|
129
|
+
* to any `MinLengthArray<N, E>` with `N <= Length` and any
|
|
130
|
+
* `MaxLengthArray<N, E>` with `N >= Length`.
|
|
131
|
+
* - The length constraint lives only in the brand, so this stays cheap for the
|
|
132
|
+
* type checker even when the element type is large — unlike
|
|
133
|
+
* `isFixedLengthTuple`, which narrows to a structural tuple type.
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
*
|
|
137
|
+
* ```ts
|
|
138
|
+
* const input: readonly number[] = [255, 128, 0];
|
|
139
|
+
*
|
|
140
|
+
* assert.isTrue(isFixedLengthArray(input, 3));
|
|
141
|
+
*
|
|
142
|
+
* assert.isFalse(isFixedLengthArray(input, 4));
|
|
143
|
+
*
|
|
144
|
+
* if (isFixedLengthArray(input, 3)) {
|
|
145
|
+
* const rgb: FixedLengthArray<3, number> = input;
|
|
146
|
+
*
|
|
147
|
+
* const atMost5: MaxLengthArray<5, number> = input; // OK (3 <= 5)
|
|
148
|
+
* }
|
|
149
|
+
* ```
|
|
150
|
+
*
|
|
151
|
+
* @template Xs - The input array type (tuple types are preserved).
|
|
152
|
+
* @template Length - The exact number of elements.
|
|
153
|
+
* @param xs - The array to check.
|
|
154
|
+
* @param length - The exact number of elements.
|
|
155
|
+
* @returns `true` if `xs.length === length`, `false` otherwise. When `true`,
|
|
156
|
+
* TypeScript narrows `xs` to `FixedLengthArray<Length, Xs[number]> & Xs`.
|
|
157
|
+
*/
|
|
158
|
+
export declare const isFixedLengthArray: <Xs extends readonly unknown[], Length extends SupportedLength>(xs: Xs, length: Length) => xs is FixedLengthArray<Length, Xs[number]> & Xs;
|
|
159
|
+
//# sourceMappingURL=is-length-bounded-array.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-length-bounded-array.d.mts","sourceRoot":"","sources":["../../src/guard/is-length-bounded-array.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,eAAe,CAAC;AAEvB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,gBAAgB,GAC3B,EAAE,SAAS,SAAS,OAAO,EAAE,EAC7B,SAAS,SAAS,eAAe,MAE7B,EAAE,aACK,SAAS,KACnB,EAAE,IAAI,cAAc,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAA4B,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,gBAAgB,GAC3B,EAAE,SAAS,SAAS,OAAO,EAAE,EAC7B,SAAS,SAAS,eAAe,MAE7B,EAAE,aACK,SAAS,KACnB,EAAE,IAAI,cAAc,CAAC,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAA4B,CAAC;AAE9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;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,EAAE,IAAI,kBAAkB,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EACd,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,kBAAkB,GAC7B,EAAE,SAAS,SAAS,OAAO,EAAE,EAC7B,MAAM,SAAS,eAAe,MAE1B,EAAE,UACE,MAAM,KACb,EAAE,IAAI,gBAAgB,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,EAA0B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
const isMinLengthArray = (xs, minLength) => xs.length >= minLength;
|
|
2
|
+
const isMaxLengthArray = (xs, maxLength) => xs.length <= maxLength;
|
|
3
|
+
const isBoundedLengthArray = (xs, minLength, maxLength) => xs.length >= minLength && xs.length <= maxLength;
|
|
4
|
+
const isFixedLengthArray = (xs, length) => xs.length === length;
|
|
5
|
+
|
|
6
|
+
export { isBoundedLengthArray, isFixedLengthArray, isMaxLengthArray, isMinLengthArray };
|
|
7
|
+
//# sourceMappingURL=is-length-bounded-array.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-length-bounded-array.mjs","sources":["../../src/guard/is-length-bounded-array.mts"],"sourcesContent":["import {\n type BoundedLengthArray,\n type FixedLengthArray,\n type MaxLengthArray,\n type MinLengthArray,\n type SupportedLength,\n} from 'ts-type-forge';\n\n/**\n * Type guard that checks if an array has at least `minLength` elements.\n *\n * **Type Narrowing Behavior:**\n *\n * - Narrows the input to `MinLengthArray<MinLength, E>` while preserving the\n * original array type (e.g. tuple types) via intersection.\n * - The length constraint lives only in the brand, so this stays cheap for the\n * type checker even when the element type is large — unlike\n * `isMinLengthTuple`, which narrows to a structural tuple type.\n * - The result participates in the length-constraint subtyping relation: for\n * example, a value narrowed to `MinLengthArray<3, E>` is assignable to\n * `MinLengthArray<1, E>`.\n *\n * @example\n *\n * ```ts\n * const input: readonly number[] = [0, 1, 2, 3];\n *\n * assert.isTrue(isMinLengthArray(input, 3));\n *\n * assert.isFalse(isMinLengthArray([0], 3));\n *\n * if (isMinLengthArray(input, 3)) {\n * const history: MinLengthArray<3, number> = input;\n *\n * const nonEmpty: MinLengthArray<1, number> = input; // OK (3 >= 1)\n * }\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 check.\n * @param minLength - The minimum number of elements (inclusive).\n * @returns `true` if `xs.length >= minLength`, `false` otherwise. When `true`,\n * TypeScript narrows `xs` to `MinLengthArray<MinLength, Xs[number]> & Xs`.\n */\nexport const isMinLengthArray = <\n Xs extends readonly unknown[],\n MinLength extends SupportedLength,\n>(\n xs: Xs,\n minLength: MinLength,\n): xs is MinLengthArray<MinLength, Xs[number]> & Xs => xs.length >= minLength;\n\n/**\n * Type guard that checks if an array has at most `maxLength` elements.\n *\n * **Type Narrowing Behavior:**\n *\n * - Narrows the input to `MaxLengthArray<MaxLength, E>` while preserving the\n * original array type (e.g. tuple types) via intersection.\n * - The length constraint lives only in the brand, so this stays cheap for the\n * type checker even when the element type is large — unlike\n * `isMaxLengthTuple`, which narrows to a union of tuple types.\n * - The result participates in the length-constraint subtyping relation: for\n * example, a value narrowed to `MaxLengthArray<8, E>` is assignable to\n * `MaxLengthArray<16, E>`.\n *\n * @example\n *\n * ```ts\n * const input: readonly string[] = ['a', 'b', 'c'];\n *\n * assert.isTrue(isMaxLengthArray(input, 8));\n *\n * assert.isFalse(isMaxLengthArray(input, 2));\n *\n * if (isMaxLengthArray(input, 8)) {\n * const tags: MaxLengthArray<8, string> = input;\n *\n * const relaxed: MaxLengthArray<16, string> = input; // OK (8 <= 16)\n * }\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 check.\n * @param maxLength - The maximum number of elements (inclusive).\n * @returns `true` if `xs.length <= maxLength`, `false` otherwise. When `true`,\n * TypeScript narrows `xs` to `MaxLengthArray<MaxLength, Xs[number]> & Xs`.\n */\nexport const isMaxLengthArray = <\n Xs extends readonly unknown[],\n MaxLength extends SupportedLength,\n>(\n xs: Xs,\n maxLength: MaxLength,\n): xs is MaxLengthArray<MaxLength, Xs[number]> & Xs => xs.length <= maxLength;\n\n/**\n * Type guard that checks if an array's length is within the inclusive range\n * `[minLength, maxLength]`.\n *\n * **Type Narrowing Behavior:**\n *\n * - Narrows the input to `BoundedLengthArray<MinLength, MaxLength, E>` while\n * preserving the original array type (e.g. tuple types) via intersection.\n * - Since `BoundedLengthArray` is the intersection of `MinLengthArray` and\n * `MaxLengthArray`, the narrowed value is assignable to both, and both\n * bounds can be weakened independently.\n * - The length constraint lives only in the brand, so this stays cheap for the\n * type checker even when the element type is large — unlike\n * `isBoundedLengthTuple`, which narrows to a union of tuple types.\n *\n * @example\n *\n * ```ts\n * const input: readonly number[] = [1, 2, 3];\n *\n * assert.isTrue(isBoundedLengthArray(input, 1, 5));\n *\n * assert.isFalse(isBoundedLengthArray([], 1, 5));\n *\n * if (isBoundedLengthArray(input, 1, 5)) {\n * const selection: BoundedLengthArray<1, 5, number> = input;\n *\n * const relaxed: BoundedLengthArray<0, 100, number> = input; // OK ([1, 5] ⊆ [0, 100])\n * }\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 check.\n * @param minLength - The minimum number of elements (inclusive).\n * @param maxLength - The maximum number of elements (inclusive).\n * @returns `true` if `minLength <= xs.length && xs.length <= maxLength`,\n * `false` otherwise. When `true`, TypeScript narrows `xs` to\n * `BoundedLengthArray<MinLength, MaxLength, Xs[number]> & Xs`.\n */\nexport const isBoundedLengthArray = <\n Xs extends readonly unknown[],\n MinLength extends SupportedLength,\n MaxLength extends SupportedLength,\n>(\n xs: Xs,\n minLength: MinLength,\n maxLength: MaxLength,\n): xs is BoundedLengthArray<MinLength, MaxLength, Xs[number]> & Xs =>\n xs.length >= minLength && xs.length <= maxLength;\n\n/**\n * Type guard that checks if an array has exactly `length` elements.\n *\n * **Type Narrowing Behavior:**\n *\n * - Narrows the input to `FixedLengthArray<Length, E>` while preserving the\n * original array type (e.g. tuple types) via intersection.\n * - Since `FixedLengthArray<Length, E>` is defined as\n * `BoundedLengthArray<Length, Length, E>`, the narrowed value is assignable\n * to any `MinLengthArray<N, E>` with `N <= Length` and any\n * `MaxLengthArray<N, E>` with `N >= Length`.\n * - The length constraint lives only in the brand, so this stays cheap for the\n * type checker even when the element type is large — unlike\n * `isFixedLengthTuple`, which narrows to a structural tuple type.\n *\n * @example\n *\n * ```ts\n * const input: readonly number[] = [255, 128, 0];\n *\n * assert.isTrue(isFixedLengthArray(input, 3));\n *\n * assert.isFalse(isFixedLengthArray(input, 4));\n *\n * if (isFixedLengthArray(input, 3)) {\n * const rgb: FixedLengthArray<3, number> = input;\n *\n * const atMost5: MaxLengthArray<5, number> = input; // OK (3 <= 5)\n * }\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 check.\n * @param length - The exact number of elements.\n * @returns `true` if `xs.length === length`, `false` otherwise. When `true`,\n * TypeScript narrows `xs` to `FixedLengthArray<Length, Xs[number]> & Xs`.\n */\nexport const isFixedLengthArray = <\n Xs extends readonly unknown[],\n Length extends SupportedLength,\n>(\n xs: Xs,\n length: Length,\n): xs is FixedLengthArray<Length, Xs[number]> & Xs => xs.length === length;\n"],"names":[],"mappings":"AA6CO,MAAM,gBAAA,GAAmB,CAI9B,EAAA,EACA,SAAA,KACqD,GAAG,MAAA,IAAU;AAuC7D,MAAM,gBAAA,GAAmB,CAI9B,EAAA,EACA,SAAA,KACqD,GAAG,MAAA,IAAU;AA2C7D,MAAM,oBAAA,GAAuB,CAKlC,EAAA,EACA,SAAA,EACA,cAEA,EAAA,CAAG,MAAA,IAAU,SAAA,IAAa,EAAA,CAAG,MAAA,IAAU;AAwClC,MAAM,kBAAA,GAAqB,CAIhC,EAAA,EACA,MAAA,KACoD,GAAG,MAAA,KAAW;;;;"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { type BoundedLengthString, type FixedLengthString, type MaxLengthString, type MinLengthString } from 'ts-type-forge';
|
|
2
|
-
import { type SizeType } from '../types.mjs';
|
|
1
|
+
import { type BoundedLengthString, type FixedLengthString, type MaxLengthString, type MinLengthString, type SupportedLength } from 'ts-type-forge';
|
|
3
2
|
/**
|
|
4
3
|
* Type guard that checks if a string has at least `minLength` characters.
|
|
5
4
|
*
|
|
@@ -38,7 +37,7 @@ import { type SizeType } from '../types.mjs';
|
|
|
38
37
|
* @returns `true` if `s.length >= minLength`, `false` otherwise. When `true`,
|
|
39
38
|
* TypeScript narrows `s` to `MinLengthString<MinLength> & S`.
|
|
40
39
|
*/
|
|
41
|
-
export declare const isMinLengthString: <S extends string, MinLength extends
|
|
40
|
+
export declare const isMinLengthString: <S extends string, MinLength extends SupportedLength>(s: S, minLength: MinLength) => s is MinLengthString<MinLength> & S;
|
|
42
41
|
/**
|
|
43
42
|
* Type guard that checks if a string has at most `maxLength` characters.
|
|
44
43
|
*
|
|
@@ -77,7 +76,7 @@ export declare const isMinLengthString: <S extends string, MinLength extends Siz
|
|
|
77
76
|
* @returns `true` if `s.length <= maxLength`, `false` otherwise. When `true`,
|
|
78
77
|
* TypeScript narrows `s` to `MaxLengthString<MaxLength> & S`.
|
|
79
78
|
*/
|
|
80
|
-
export declare const isMaxLengthString: <S extends string, MaxLength extends
|
|
79
|
+
export declare const isMaxLengthString: <S extends string, MaxLength extends SupportedLength>(s: S, maxLength: MaxLength) => s is MaxLengthString<MaxLength> & S;
|
|
81
80
|
/**
|
|
82
81
|
* Type guard that checks if a string's length is within the inclusive range
|
|
83
82
|
* `[minLength, maxLength]`.
|
|
@@ -120,7 +119,7 @@ export declare const isMaxLengthString: <S extends string, MaxLength extends Siz
|
|
|
120
119
|
* otherwise. When `true`, TypeScript narrows `s` to
|
|
121
120
|
* `BoundedLengthString<MinLength, MaxLength> & S`.
|
|
122
121
|
*/
|
|
123
|
-
export declare const isBoundedLengthString: <S extends string, MinLength extends
|
|
122
|
+
export declare const isBoundedLengthString: <S extends string, MinLength extends SupportedLength, MaxLength extends SupportedLength>(s: S, minLength: MinLength, maxLength: MaxLength) => s is BoundedLengthString<MinLength, MaxLength> & S;
|
|
124
123
|
/**
|
|
125
124
|
* Type guard that checks if a string has exactly `length` characters.
|
|
126
125
|
*
|
|
@@ -160,5 +159,5 @@ export declare const isBoundedLengthString: <S extends string, MinLength extends
|
|
|
160
159
|
* @returns `true` if `s.length === length`, `false` otherwise. When `true`,
|
|
161
160
|
* TypeScript narrows `s` to `FixedLengthString<Length> & S`.
|
|
162
161
|
*/
|
|
163
|
-
export declare const isFixedLengthString: <S extends string, Length extends
|
|
162
|
+
export declare const isFixedLengthString: <S extends string, Length extends SupportedLength>(s: S, length: Length) => s is FixedLengthString<Length> & S;
|
|
164
163
|
//# sourceMappingURL=is-length-bounded-string.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"is-length-bounded-string.d.mts","sourceRoot":"","sources":["../../src/guard/is-length-bounded-string.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,eAAe,
|
|
1
|
+
{"version":3,"file":"is-length-bounded-string.d.mts","sourceRoot":"","sources":["../../src/guard/is-length-bounded-string.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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,iBAAiB,GAC5B,CAAC,SAAS,MAAM,EAChB,SAAS,SAAS,eAAe,KAE9B,CAAC,aACO,SAAS,KACnB,CAAC,IAAI,eAAe,CAAC,SAAS,CAAC,GAAG,CAA0B,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,eAAO,MAAM,iBAAiB,GAC5B,CAAC,SAAS,MAAM,EAChB,SAAS,SAAS,eAAe,KAE9B,CAAC,aACO,SAAS,KACnB,CAAC,IAAI,eAAe,CAAC,SAAS,CAAC,GAAG,CAA0B,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,eAAO,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;AAEjD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,eAAO,MAAM,mBAAmB,GAC9B,CAAC,SAAS,MAAM,EAChB,MAAM,SAAS,eAAe,KAE3B,CAAC,UACI,MAAM,KACb,CAAC,IAAI,iBAAiB,CAAC,MAAM,CAAC,GAAG,CAAwB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"is-length-bounded-string.mjs","sources":["../../src/guard/is-length-bounded-string.mts"],"sourcesContent":["import {\n type BoundedLengthString,\n type FixedLengthString,\n type MaxLengthString,\n type MinLengthString,\n} from 'ts-type-forge';\
|
|
1
|
+
{"version":3,"file":"is-length-bounded-string.mjs","sources":["../../src/guard/is-length-bounded-string.mts"],"sourcesContent":["import {\n type BoundedLengthString,\n type FixedLengthString,\n type MaxLengthString,\n type MinLengthString,\n type SupportedLength,\n} from 'ts-type-forge';\n\n/**\n * Type guard that checks if a string has at least `minLength` characters.\n *\n * The length is 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 *\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(isMinLengthString(input, 12));\n *\n * assert.isFalse(isMinLengthString('short', 12));\n *\n * if (isMinLengthString(input, 12)) {\n * const password: MinLengthString<12> = input;\n *\n * const nonEmpty: NonEmptyString = input; // OK (12 >= 1)\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 */\nexport 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 * The length is 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 *\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(isMaxLengthString(input, 32));\n *\n * assert.isFalse(isMaxLengthString(input, 3));\n *\n * if (isMaxLengthString(input, 32)) {\n * const userName: MaxLengthString<32> = input;\n *\n * const relaxed: MaxLengthString<64> = input; // OK (32 <= 64)\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 */\nexport 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 * The length is 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 *\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(isBoundedLengthString(input, 8, 16));\n *\n * assert.isFalse(isBoundedLengthString('user', 8, 16));\n *\n * if (isBoundedLengthString(input, 8, 16)) {\n * const userId: BoundedLengthString<8, 16> = input;\n *\n * const relaxed: BoundedLengthString<1, 255> = input; // OK ([8, 16] ⊆ [1, 255])\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 */\nexport 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 * The length is 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 *\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(isFixedLengthString(input, 2));\n *\n * assert.isFalse(isFixedLengthString(input, 3));\n *\n * if (isFixedLengthString(input, 2)) {\n * const countryCode: FixedLengthString<2> = input;\n *\n * const atMost5: MaxLengthString<5> = input; // OK (2 <= 5)\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 */\nexport 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"],"names":[],"mappings":"AA8CO,MAAM,iBAAA,GAAoB,CAI/B,CAAA,EACA,SAAA,KACwC,EAAE,MAAA,IAAU;AAwC/C,MAAM,iBAAA,GAAoB,CAI/B,CAAA,EACA,SAAA,KACwC,EAAE,MAAA,IAAU;AA4C/C,MAAM,qBAAA,GAAwB,CAKnC,CAAA,EACA,SAAA,EACA,cAEA,CAAA,CAAE,MAAA,IAAU,SAAA,IAAa,CAAA,CAAE,MAAA,IAAU;AAyChC,MAAM,mBAAA,GAAsB,CAIjC,CAAA,EACA,MAAA,KACuC,EAAE,MAAA,KAAW;;;;"}
|
package/dist/index.mjs
CHANGED
|
@@ -5,7 +5,9 @@ export { ISet } from './collections/iset.mjs';
|
|
|
5
5
|
export { createQueue } from './collections/queue.mjs';
|
|
6
6
|
export { createStack } from './collections/stack.mjs';
|
|
7
7
|
export { expectType } from './expect-type.mjs';
|
|
8
|
+
export { asBoundedLengthArray, asFixedLengthArray, asMaxLengthArray, asMinLengthArray } from './guard/as-length-bounded-array.mjs';
|
|
8
9
|
export { hasKey } from './guard/has-key.mjs';
|
|
10
|
+
export { isBoundedLengthArray, isFixedLengthArray, isMaxLengthArray, isMinLengthArray } from './guard/is-length-bounded-array.mjs';
|
|
9
11
|
export { isBoundedLengthString, isFixedLengthString, isMaxLengthString, isMinLengthString } from './guard/is-length-bounded-string.mjs';
|
|
10
12
|
export { isNonEmptyString } from './guard/is-non-empty-string.mjs';
|
|
11
13
|
export { isNonNullObject } from './guard/is-non-null-object.mjs';
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|