ts-data-forge 12.2.2 → 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.
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type BoolOr, type BoundedLengthTuple, type FixedLengthTuple, type MaxLengthTuple, type
|
|
1
|
+
import { type BoolOr, type BoundedLengthTuple, type FixedLengthArray, type FixedLengthTuple, type MaxLengthTuple, type MinLengthArray, type MinLengthTuple, type TypeEq } from 'ts-type-forge';
|
|
2
2
|
import { type ArrayIndex, type SizeType } from '../../types.mjs';
|
|
3
3
|
/**
|
|
4
4
|
* Type guard that checks if a value is an array.
|
|
@@ -37,11 +37,13 @@ type Cast<A, B> = A extends B ? A : never;
|
|
|
37
37
|
* assert.isFalse(Arr.isEmpty(words));
|
|
38
38
|
*
|
|
39
39
|
* if (Arr.isEmpty(emptyNumbers)) {
|
|
40
|
-
*
|
|
40
|
+
* // `isEmpty` narrows to the branded `FixedLengthArray<0, number>`, so the
|
|
41
|
+
* // expected value is annotated with the unbranded type.
|
|
42
|
+
* assert.deepStrictEqual<readonly number[]>(emptyNumbers, []);
|
|
41
43
|
* }
|
|
42
44
|
* ```
|
|
43
45
|
*/
|
|
44
|
-
export declare const isEmpty: <
|
|
46
|
+
export declare const isEmpty: <Xs extends readonly unknown[]>(array: Xs) => array is FixedLengthArray<0, Xs[number]> & Xs;
|
|
45
47
|
/**
|
|
46
48
|
* Type guard that checks if an array is non-empty.
|
|
47
49
|
*
|
|
@@ -61,7 +63,7 @@ export declare const isEmpty: <E>(array: readonly E[]) => array is readonly [];
|
|
|
61
63
|
* }
|
|
62
64
|
* ```
|
|
63
65
|
*/
|
|
64
|
-
export declare const isNonEmpty: <
|
|
66
|
+
export declare const isNonEmpty: <Xs extends readonly unknown[]>(array: Xs) => array is MinLengthArray<1, Xs[number]> & Xs;
|
|
65
67
|
/**
|
|
66
68
|
* Checks if an array has a specific length.
|
|
67
69
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array-utils-validation.d.mts","sourceRoot":"","sources":["../../../src/array/impl/array-utils-validation.mts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,MAAM,EACX,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,
|
|
1
|
+
{"version":3,"file":"array-utils-validation.d.mts","sourceRoot":"","sources":["../../../src/array/impl/array-utils-validation.mts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
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 return everyImpl(...args);\n\n case 1:\n return (array) => everyImpl(array, ...args);\n }\n}\n\nconst everyImpl = <E,>(\n array: readonly E[],\n predicate: (a: E, index: SizeType.Arr) => boolean,\n): boolean => array.every((a, i) => predicate(a, asUint32(i)));\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 return someImpl(...args);\n\n case 1:\n return (array) => someImpl(array, ...args);\n }\n}\n\nconst someImpl = <E,>(\n array: readonly E[],\n predicate: (a: E, index: SizeType.Arr) => boolean,\n): boolean => array.some((a, i) => predicate(a, asUint32(i)));\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;AACH,MAAA,OAAO,SAAA,CAAU,GAAG,IAAI,CAAA;AAAA,IAE1B,KAAK,CAAA;AACH,MAAA,OAAO,CAAC,KAAA,KAAU,SAAA,CAAU,KAAA,EAAO,GAAG,IAAI,CAAA;AAAA;AAEhD;AAEA,MAAM,SAAA,GAAY,CAChB,KAAA,EACA,SAAA,KACY,MAAM,KAAA,CAAM,CAAC,CAAA,EAAG,CAAA,KAAM,SAAA,CAAU,CAAA,EAAG,QAAA,CAAS,CAAC,CAAC,CAAC,CAAA;AA8BtD,SAAS,QACX,IAAA,EAM2C;AAC9C,EAAA,QAAQ,KAAK,MAAA;AAAQ,IACnB,KAAK,CAAA;AACH,MAAA,OAAO,QAAA,CAAS,GAAG,IAAI,CAAA;AAAA,IAEzB,KAAK,CAAA;AACH,MAAA,OAAO,CAAC,KAAA,KAAU,QAAA,CAAS,KAAA,EAAO,GAAG,IAAI,CAAA;AAAA;AAE/C;AAEA,MAAM,QAAA,GAAW,CACf,KAAA,EACA,SAAA,KACY,MAAM,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,SAAA,CAAU,CAAA,EAAG,QAAA,CAAS,CAAC,CAAC,CAAC,CAAA;AAmBrD,MAAM,cAAA,GAAiB,CAC5B,KAAA,EACA,KAAA,KACY,GAAA,CAAI,UAAU,CAAA,EAAG,KAAA,CAAM,MAAM,CAAA,CAAE,KAAK;;;;"}
|
|
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 FixedLengthArray,\n type FixedLengthTuple,\n type MaxLengthTuple,\n type MinLengthArray,\n type MinLengthTuple,\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 * // `isEmpty` narrows to the branded `FixedLengthArray<0, number>`, so the\n * // expected value is annotated with the unbranded type.\n * assert.deepStrictEqual<readonly number[]>(emptyNumbers, []);\n * }\n * ```\n */\nexport const isEmpty = <Xs extends readonly unknown[]>(\n array: Xs,\n): array is FixedLengthArray<0, Xs[number]> & Xs => 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 = <Xs extends readonly unknown[]>(\n array: Xs,\n): array is MinLengthArray<1, Xs[number]> & Xs => 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 return everyImpl(...args);\n\n case 1:\n return (array) => everyImpl(array, ...args);\n }\n}\n\nconst everyImpl = <E,>(\n array: readonly E[],\n predicate: (a: E, index: SizeType.Arr) => boolean,\n): boolean => array.every((a, i) => predicate(a, asUint32(i)));\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 return someImpl(...args);\n\n case 1:\n return (array) => someImpl(array, ...args);\n }\n}\n\nconst someImpl = <E,>(\n array: readonly E[],\n predicate: (a: E, index: SizeType.Arr) => boolean,\n): boolean => array.some((a, i) => predicate(a, asUint32(i)));\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCO,MAAM,OAAA,GAAU,CAAK,KAAA,KAC1B,KAAA,CAAM,QAAQ,KAAK;AAoCd,MAAM,OAAA,GAAU,CACrB,KAAA,KACkD,KAAA,CAAM,MAAA,KAAW;AAqB9D,MAAM,UAAA,GAAa,CACxB,KAAA,KACgD,KAAA,CAAM,MAAA,GAAS;AAqB1D,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;AACH,MAAA,OAAO,SAAA,CAAU,GAAG,IAAI,CAAA;AAAA,IAE1B,KAAK,CAAA;AACH,MAAA,OAAO,CAAC,KAAA,KAAU,SAAA,CAAU,KAAA,EAAO,GAAG,IAAI,CAAA;AAAA;AAEhD;AAEA,MAAM,SAAA,GAAY,CAChB,KAAA,EACA,SAAA,KACY,MAAM,KAAA,CAAM,CAAC,CAAA,EAAG,CAAA,KAAM,SAAA,CAAU,CAAA,EAAG,QAAA,CAAS,CAAC,CAAC,CAAC,CAAA;AA8BtD,SAAS,QACX,IAAA,EAM2C;AAC9C,EAAA,QAAQ,KAAK,MAAA;AAAQ,IACnB,KAAK,CAAA;AACH,MAAA,OAAO,QAAA,CAAS,GAAG,IAAI,CAAA;AAAA,IAEzB,KAAK,CAAA;AACH,MAAA,OAAO,CAAC,KAAA,KAAU,QAAA,CAAS,KAAA,EAAO,GAAG,IAAI,CAAA;AAAA;AAE/C;AAEA,MAAM,QAAA,GAAW,CACf,KAAA,EACA,SAAA,KACY,MAAM,IAAA,CAAK,CAAC,CAAA,EAAG,CAAA,KAAM,SAAA,CAAU,CAAA,EAAG,QAAA,CAAS,CAAC,CAAC,CAAC,CAAA;AAmBrD,MAAM,cAAA,GAAiB,CAC5B,KAAA,EACA,KAAA,KACY,GAAA,CAAI,UAAU,CAAA,EAAG,KAAA,CAAM,MAAM,CAAA,CAAE,KAAK;;;;"}
|
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",
|
|
@@ -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",
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type BoolOr,
|
|
3
3
|
type BoundedLengthTuple,
|
|
4
|
+
type FixedLengthArray,
|
|
4
5
|
type FixedLengthTuple,
|
|
5
6
|
type MaxLengthTuple,
|
|
7
|
+
type MinLengthArray,
|
|
6
8
|
type MinLengthTuple,
|
|
7
|
-
type NonEmptyArray,
|
|
8
9
|
type TypeEq,
|
|
9
10
|
} from 'ts-type-forge';
|
|
10
11
|
import { asUint32, Num } from '../../number/index.mjs';
|
|
@@ -60,12 +61,15 @@ type Cast<A, B> = A extends B ? A : never;
|
|
|
60
61
|
* assert.isFalse(Arr.isEmpty(words));
|
|
61
62
|
*
|
|
62
63
|
* if (Arr.isEmpty(emptyNumbers)) {
|
|
63
|
-
*
|
|
64
|
+
* // `isEmpty` narrows to the branded `FixedLengthArray<0, number>`, so the
|
|
65
|
+
* // expected value is annotated with the unbranded type.
|
|
66
|
+
* assert.deepStrictEqual<readonly number[]>(emptyNumbers, []);
|
|
64
67
|
* }
|
|
65
68
|
* ```
|
|
66
69
|
*/
|
|
67
|
-
export const isEmpty = <
|
|
68
|
-
array
|
|
70
|
+
export const isEmpty = <Xs extends readonly unknown[]>(
|
|
71
|
+
array: Xs,
|
|
72
|
+
): array is FixedLengthArray<0, Xs[number]> & Xs => array.length === 0;
|
|
69
73
|
|
|
70
74
|
/**
|
|
71
75
|
* Type guard that checks if an array is non-empty.
|
|
@@ -86,9 +90,9 @@ export const isEmpty = <E,>(array: readonly E[]): array is readonly [] =>
|
|
|
86
90
|
* }
|
|
87
91
|
* ```
|
|
88
92
|
*/
|
|
89
|
-
export const isNonEmpty = <
|
|
90
|
-
array:
|
|
91
|
-
): array is
|
|
93
|
+
export const isNonEmpty = <Xs extends readonly unknown[]>(
|
|
94
|
+
array: Xs,
|
|
95
|
+
): array is MinLengthArray<1, Xs[number]> & Xs => array.length > 0;
|
|
92
96
|
|
|
93
97
|
/**
|
|
94
98
|
* Checks if an array has a specific length.
|