ts-fortress 10.0.0 → 11.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/array/bounded-length-array.d.mts +29 -0
  2. package/dist/array/bounded-length-array.d.mts.map +1 -0
  3. package/dist/array/bounded-length-array.mjs +54 -0
  4. package/dist/array/bounded-length-array.mjs.map +1 -0
  5. package/dist/array/build-type.d.mts +28 -0
  6. package/dist/array/build-type.d.mts.map +1 -0
  7. package/dist/array/build-type.mjs +44 -0
  8. package/dist/array/build-type.mjs.map +1 -0
  9. package/dist/array/fixed-length-array.d.mts +23 -0
  10. package/dist/array/fixed-length-array.d.mts.map +1 -0
  11. package/dist/array/fixed-length-array.mjs +46 -0
  12. package/dist/array/fixed-length-array.mjs.map +1 -0
  13. package/dist/array/index.d.mts +4 -1
  14. package/dist/array/index.d.mts.map +1 -1
  15. package/dist/array/index.mjs +4 -1
  16. package/dist/array/index.mjs.map +1 -1
  17. package/dist/array/max-length-array.d.mts +21 -0
  18. package/dist/array/max-length-array.d.mts.map +1 -0
  19. package/dist/array/max-length-array.mjs +50 -0
  20. package/dist/array/max-length-array.mjs.map +1 -0
  21. package/dist/array/min-length-array.d.mts +21 -0
  22. package/dist/array/min-length-array.d.mts.map +1 -0
  23. package/dist/array/min-length-array.mjs +52 -0
  24. package/dist/array/min-length-array.mjs.map +1 -0
  25. package/dist/array/non-empty-array.d.mts +2 -2
  26. package/dist/array/non-empty-array.d.mts.map +1 -1
  27. package/dist/array/non-empty-array.mjs +7 -15
  28. package/dist/array/non-empty-array.mjs.map +1 -1
  29. package/dist/compose/intersection.d.mts +6 -6
  30. package/dist/compose/intersection.mjs.map +1 -1
  31. package/dist/compose/union.d.mts +5 -5
  32. package/dist/compose/union.mjs.map +1 -1
  33. package/dist/entry-point.mjs +4 -1
  34. package/dist/entry-point.mjs.map +1 -1
  35. package/dist/enum/enum.d.mts +3 -3
  36. package/dist/enum/enum.mjs.map +1 -1
  37. package/dist/index.mjs +4 -1
  38. package/dist/index.mjs.map +1 -1
  39. package/dist/record/merge-records.d.mts +2 -2
  40. package/dist/record/merge-records.mjs.map +1 -1
  41. package/dist/record/partial.d.mts +4 -4
  42. package/dist/record/partial.mjs.map +1 -1
  43. package/dist/record/required.d.mts +4 -4
  44. package/dist/record/required.mjs.map +1 -1
  45. package/package.json +4 -4
  46. package/src/array/bounded-length-array.mts +156 -0
  47. package/src/array/bounded-length-array.test.mts +66 -0
  48. package/src/array/build-type.mts +82 -0
  49. package/src/array/fixed-length-array.mts +108 -0
  50. package/src/array/fixed-length-array.test.mts +70 -0
  51. package/src/array/index.mts +4 -1
  52. package/src/array/max-length-array.mts +109 -0
  53. package/src/array/max-length-array.test.mts +52 -0
  54. package/src/array/min-length-array.mts +114 -0
  55. package/src/array/min-length-array.test.mts +54 -0
  56. package/src/array/non-empty-array.mts +17 -25
  57. package/src/array/non-empty-array.test.mts +13 -7
  58. package/src/compose/intersection.mts +6 -6
  59. package/src/compose/union.mts +5 -5
  60. package/src/enum/enum.mts +4 -4
  61. package/src/record/merge-records.mts +3 -3
  62. package/src/record/partial.mts +6 -6
  63. package/src/record/required.mts +4 -4
  64. package/dist/array/length-constrained-array.d.mts +0 -82
  65. package/dist/array/length-constrained-array.d.mts.map +0 -1
  66. package/dist/array/length-constrained-array.mjs +0 -215
  67. package/dist/array/length-constrained-array.mjs.map +0 -1
  68. package/src/array/length-constrained-array.mts +0 -514
  69. package/src/array/length-constrained-array.test.mts +0 -229
@@ -0,0 +1,29 @@
1
+ import { type BoundedLengthArray, type MaxLengthArray, type MinLengthArray, type SupportedLength } from 'ts-type-forge';
2
+ import { type Type } from '../type.mjs';
3
+ export type { BoundedLengthArray } from 'ts-type-forge';
4
+ /**
5
+ * Creates a `Type` for a readonly array whose length is within the inclusive
6
+ * range `[min, max]`, typed as the branded {@link BoundedLengthArray} instead
7
+ * of the union of tuple types produced by `boundedLengthTuple`.
8
+ *
9
+ * Because the length constraint lives only in the brand, no union of tuples
10
+ * of the element type is ever constructed, which keeps type-checking cheap
11
+ * even when `A` is a large type.
12
+ */
13
+ export declare function boundedLengthArray<A, Min extends SupportedLength, Max extends SupportedLength>(min: Min, max: Max, elementType: Type<A>, options?: Partial<Readonly<{
14
+ typeName: string;
15
+ defaultValue: BoundedLengthArray<Min, Max, A>;
16
+ }>>): Type<BoundedLengthArray<Min, Max, A>>;
17
+ export declare function boundedLengthArray<A, Min extends SupportedLength>(min: Min, max: number, elementType: Type<A>, options?: Partial<Readonly<{
18
+ typeName: string;
19
+ defaultValue: MinLengthArray<Min, A>;
20
+ }>>): Type<MinLengthArray<Min, A>>;
21
+ export declare function boundedLengthArray<A, Max extends SupportedLength>(min: number, max: Max, elementType: Type<A>, options?: Partial<Readonly<{
22
+ typeName: string;
23
+ defaultValue: MaxLengthArray<Max, A>;
24
+ }>>): Type<MaxLengthArray<Max, A>>;
25
+ export declare function boundedLengthArray<A>(min: number, max: number, elementType: Type<A>, options?: Partial<Readonly<{
26
+ typeName: string;
27
+ defaultValue: readonly A[];
28
+ }>>): Type<readonly A[]>;
29
+ //# sourceMappingURL=bounded-length-array.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded-length-array.d.mts","sourceRoot":"","sources":["../../src/array/bounded-length-array.mts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,kBAAkB,EACvB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,eAAe,EACrB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAOxC,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAExD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,CAAC,EACD,GAAG,SAAS,eAAe,EAC3B,GAAG,SAAS,eAAe,EAE3B,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,kBAAkB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;CAC/C,CAAC,CACH,GACA,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AAIzC,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,GAAG,SAAS,eAAe,EAC/D,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;CACtC,CAAC,CACH,GACA,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AAIhC,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,GAAG,SAAS,eAAe,EAC/D,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,GAAG,EACR,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;CACtC,CAAC,CACH,GACA,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AAGhC,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC;CAC5B,CAAC,CACH,GACA,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { memoizeFunction, Arr, asUint32, Result } from 'ts-data-forge';
2
+ import { createPrimitiveValidationError } from '../utils/validation-error.mjs';
3
+ import { buildType, validateElements } from './build-type.mjs';
4
+
5
+ function boundedLengthArray(min, max, elementType, options) {
6
+ const typeName = options?.typeName ?? `BoundedLengthArray<${min}, ${max}, ${elementType.typeName}>`;
7
+ const getDefaultValue = memoizeFunction(
8
+ () => options?.defaultValue ?? // An array of the minimum length is the shortest value within the range.
9
+ Arr.create(asUint32(min), elementType.defaultValue)
10
+ );
11
+ const validate = (a) => {
12
+ if (!Arr.isArray(a)) {
13
+ return Result.err([
14
+ createPrimitiveValidationError({
15
+ actualValue: a,
16
+ expectedType: "array",
17
+ typeName,
18
+ details: void 0
19
+ })
20
+ ]);
21
+ }
22
+ if (a.length < min || max < a.length) {
23
+ return Result.err([
24
+ {
25
+ path: [],
26
+ actualValue: a,
27
+ expectedType: typeName,
28
+ typeName,
29
+ details: {
30
+ kind: "array-range-length",
31
+ minLength: min,
32
+ maxLength: max,
33
+ actualLength: a.length
34
+ }
35
+ }
36
+ ]);
37
+ }
38
+ return validateElements(a, elementType);
39
+ };
40
+ const fill = (a) => {
41
+ if (!Arr.isArray(a)) {
42
+ return getDefaultValue();
43
+ }
44
+ const capped = Arr.take(a, asUint32(max));
45
+ return capped.length >= min ? Arr.map(capped, (el) => elementType.fill(el)) : Arr.map(
46
+ Arr.seq(asUint32(min)),
47
+ (i) => elementType.fill(capped[i])
48
+ );
49
+ };
50
+ return buildType({ typeName, getDefaultValue, validate, fill, elementType });
51
+ }
52
+
53
+ export { boundedLengthArray };
54
+ //# sourceMappingURL=bounded-length-array.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bounded-length-array.mjs","sources":["../../src/array/bounded-length-array.mts"],"sourcesContent":["import { Arr, asUint32, memoizeFunction, Result } from 'ts-data-forge';\nimport {\n type BoundedLengthArray,\n type MaxLengthArray,\n type MinLengthArray,\n type SupportedLength,\n} from 'ts-type-forge';\nimport { type Type } from '../type.mjs';\nimport {\n createPrimitiveValidationError,\n type ValidationError,\n} from '../utils/index.mjs';\nimport { buildType, validateElements } from './build-type.mjs';\n\nexport type { BoundedLengthArray } from 'ts-type-forge';\n\n/**\n * Creates a `Type` for a readonly array whose length is within the inclusive\n * range `[min, max]`, typed as the branded {@link BoundedLengthArray} instead\n * of the union of tuple types produced by `boundedLengthTuple`.\n *\n * Because the length constraint lives only in the brand, no union of tuples\n * of the element type is ever constructed, which keeps type-checking cheap\n * even when `A` is a large type.\n */\nexport function boundedLengthArray<\n A,\n Min extends SupportedLength,\n Max extends SupportedLength,\n>(\n min: Min,\n max: Max,\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: BoundedLengthArray<Min, Max, A>;\n }>\n >,\n): Type<BoundedLengthArray<Min, Max, A>>;\n\n// Only the lower bound is in `SupportedLength`, so the upper bound is dropped from\n// the result type and only the \"at least `min`\" guarantee is kept.\nexport function boundedLengthArray<A, Min extends SupportedLength>(\n min: Min,\n max: number,\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: MinLengthArray<Min, A>;\n }>\n >,\n): Type<MinLengthArray<Min, A>>;\n\n// Only the upper bound is in `SupportedLength`, so the lower bound is dropped from\n// the result type and only the \"at most `max`\" guarantee is kept.\nexport function boundedLengthArray<A, Max extends SupportedLength>(\n min: number,\n max: Max,\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: MaxLengthArray<Max, A>;\n }>\n >,\n): Type<MaxLengthArray<Max, A>>;\n\n// Neither bound is in `SupportedLength`, so the result length is left unconstrained.\nexport function boundedLengthArray<A>(\n min: number,\n max: number,\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: readonly A[];\n }>\n >,\n): Type<readonly A[]>;\n\nexport function boundedLengthArray<A>(\n min: number,\n max: number,\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: readonly A[];\n }>\n >,\n): Type<readonly A[]> {\n type T = readonly A[];\n\n const typeName =\n options?.typeName ??\n `BoundedLengthArray<${min}, ${max}, ${elementType.typeName}>`;\n\n const getDefaultValue = memoizeFunction(\n (): T =>\n options?.defaultValue ??\n // An array of the minimum length is the shortest value within the range.\n Arr.create(asUint32(min), elementType.defaultValue),\n );\n\n const validate: Type<T>['validate'] = (a) => {\n if (!Arr.isArray(a)) {\n return Result.err([\n createPrimitiveValidationError({\n actualValue: a,\n expectedType: 'array',\n typeName,\n details: undefined,\n }),\n ]);\n }\n\n if (a.length < min || max < a.length) {\n return Result.err([\n {\n path: [],\n actualValue: a,\n expectedType: typeName,\n typeName,\n details: {\n kind: 'array-range-length',\n minLength: min,\n maxLength: max,\n actualLength: a.length,\n },\n } satisfies ValidationError,\n ]);\n }\n\n return validateElements(a, elementType);\n };\n\n const fill: Type<T>['fill'] = (a) => {\n if (!Arr.isArray(a)) {\n return getDefaultValue();\n }\n\n // Trim down to at most `max`, then pad up to at least `min`.\n const capped = Arr.take(a, asUint32(max));\n\n return capped.length >= min\n ? Arr.map(capped, (el) => elementType.fill(el) satisfies A)\n : Arr.map(\n Arr.seq(asUint32(min)),\n (i) => elementType.fill(capped[i]) satisfies A,\n );\n };\n\n return buildType({ typeName, getDefaultValue, validate, fill, elementType });\n}\n"],"names":[],"mappings":";;;;AAkFO,SAAS,kBAAA,CACd,GAAA,EACA,GAAA,EACA,WAAA,EACA,OAAA,EAMoB;AAGpB,EAAA,MAAM,QAAA,GACJ,SAAS,QAAA,IACT,CAAA,mBAAA,EAAsB,GAAG,CAAA,EAAA,EAAK,GAAG,CAAA,EAAA,EAAK,WAAA,CAAY,QAAQ,CAAA,CAAA,CAAA;AAE5D,EAAA,MAAM,eAAA,GAAkB,eAAA;AAAA,IACtB,MACE,OAAA,EAAS,YAAA;AAAA,IAET,IAAI,MAAA,CAAO,QAAA,CAAS,GAAG,CAAA,EAAG,YAAY,YAAY;AAAA,GACtD;AAEA,EAAA,MAAM,QAAA,GAAgC,CAAC,CAAA,KAAM;AAC3C,IAAA,IAAI,CAAC,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAA,EAAG;AACnB,MAAA,OAAO,OAAO,GAAA,CAAI;AAAA,QAChB,8BAAA,CAA+B;AAAA,UAC7B,WAAA,EAAa,CAAA;AAAA,UACb,YAAA,EAAc,OAAA;AAAA,UACd,QAAA;AAAA,UACA,OAAA,EAAS;AAAA,SACV;AAAA,OACF,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,CAAA,CAAE,MAAA,GAAS,GAAA,IAAO,GAAA,GAAM,EAAE,MAAA,EAAQ;AACpC,MAAA,OAAO,OAAO,GAAA,CAAI;AAAA,QAChB;AAAA,UACE,MAAM,EAAC;AAAA,UACP,WAAA,EAAa,CAAA;AAAA,UACb,YAAA,EAAc,QAAA;AAAA,UACd,QAAA;AAAA,UACA,OAAA,EAAS;AAAA,YACP,IAAA,EAAM,oBAAA;AAAA,YACN,SAAA,EAAW,GAAA;AAAA,YACX,SAAA,EAAW,GAAA;AAAA,YACX,cAAc,CAAA,CAAE;AAAA;AAClB;AACF,OACD,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,gBAAA,CAAiB,GAAG,WAAW,CAAA;AAAA,EACxC,CAAA;AAEA,EAAA,MAAM,IAAA,GAAwB,CAAC,CAAA,KAAM;AACnC,IAAA,IAAI,CAAC,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAA,EAAG;AACnB,MAAA,OAAO,eAAA,EAAgB;AAAA,IACzB;AAGA,IAAA,MAAM,SAAS,GAAA,CAAI,IAAA,CAAK,CAAA,EAAG,QAAA,CAAS,GAAG,CAAC,CAAA;AAExC,IAAA,OAAO,MAAA,CAAO,MAAA,IAAU,GAAA,GACpB,GAAA,CAAI,GAAA,CAAI,MAAA,EAAQ,CAAC,EAAA,KAAO,WAAA,CAAY,IAAA,CAAK,EAAE,CAAa,IACxD,GAAA,CAAI,GAAA;AAAA,MACF,GAAA,CAAI,GAAA,CAAI,QAAA,CAAS,GAAG,CAAC,CAAA;AAAA,MACrB,CAAC,CAAA,KAAM,WAAA,CAAY,IAAA,CAAK,MAAA,CAAO,CAAC,CAAC;AAAA,KACnC;AAAA,EACN,CAAA;AAEA,EAAA,OAAO,UAAU,EAAE,QAAA,EAAU,iBAAiB,QAAA,EAAU,IAAA,EAAM,aAAa,CAAA;AAC7E;;;;"}
@@ -0,0 +1,28 @@
1
+ import { Result } from 'ts-data-forge';
2
+ import { type Type } from '../type.mjs';
3
+ import { type ValidationError } from '../utils/index.mjs';
4
+ /**
5
+ * Validates each element of `a` against `elementType`, collecting any element
6
+ * errors with their index prepended. Shared by the length-constrained array
7
+ * validators.
8
+ *
9
+ * @internal Not part of the public package API.
10
+ */
11
+ export declare const validateElements: <A>(a: readonly unknown[], elementType: Type<A>) => Result<readonly A[], readonly ValidationError[]>;
12
+ /**
13
+ * Assembles a structural `Type<readonly A[]>` from the length-specific pieces
14
+ * (`typeName` / `getDefaultValue` / `validate` / `fill`). Shared internally by
15
+ * the length-constrained array validators (`fixedLengthArray` etc.) and the
16
+ * `nonEmptyArray` validator; their outer signatures narrow the structural
17
+ * result to the branded array type.
18
+ *
19
+ * @internal Not part of the public package API.
20
+ */
21
+ export declare const buildType: <Elm, T extends readonly Elm[] = readonly Elm[]>({ typeName, getDefaultValue, validate, fill, elementType, }: Readonly<{
22
+ typeName: string;
23
+ getDefaultValue: () => readonly Elm[];
24
+ validate: (a: unknown) => Result<readonly Elm[], readonly ValidationError[]>;
25
+ fill: (a: unknown) => readonly Elm[];
26
+ elementType: Type<Elm>;
27
+ }>) => Type<T>;
28
+ //# sourceMappingURL=build-type.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-type.d.mts","sourceRoot":"","sources":["../../src/array/build-type.mts"],"names":[],"mappings":"AAAA,OAAO,EAAO,MAAM,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAKL,KAAK,eAAe,EACrB,MAAM,oBAAoB,CAAC;AAE5B;;;;;;GAMG;AACH,eAAO,MAAM,gBAAgB,GAAI,CAAC,KAC7B,SAAS,OAAO,EAAE,eACR,IAAI,CAAC,CAAC,CAAC,KACnB,MAAM,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,eAAe,EAAE,CAiBjD,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,SAAS,GAAI,GAAG,EAAE,CAAC,SAAS,SAAS,GAAG,EAAE,GAAG,SAAS,GAAG,EAAE,+DAMrE,QAAQ,CAAC;IACV,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,SAAS,GAAG,EAAE,CAAC;IACtC,QAAQ,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,CAAC,SAAS,GAAG,EAAE,EAAE,SAAS,eAAe,EAAE,CAAC,CAAC;IAC7E,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,SAAS,GAAG,EAAE,CAAC;IACrC,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;CACxB,CAAC,KAAG,IAAI,CAAC,CAAC,CAqBV,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { Arr, Result } from 'ts-data-forge';
2
+ import { createAssertFn } from '../utils/create-assert-fn.mjs';
3
+ import { createCastFn } from '../utils/create-cast-fn.mjs';
4
+ import { createIsFn } from '../utils/create-is-fn.mjs';
5
+ import { prependIndexToValidationErrors } from '../utils/validation-error.mjs';
6
+
7
+ const validateElements = (a, elementType) => {
8
+ const errors = Arr.generate(function* () {
9
+ for (const [index, el] of a.entries()) {
10
+ const res = elementType.validate(el);
11
+ if (Result.isErr(res)) {
12
+ yield* prependIndexToValidationErrors(res.value, index);
13
+ }
14
+ }
15
+ });
16
+ if (Arr.isNonEmpty(errors)) {
17
+ return Result.err(errors);
18
+ }
19
+ return Result.ok(a);
20
+ };
21
+ const buildType = ({
22
+ typeName,
23
+ getDefaultValue,
24
+ validate,
25
+ fill,
26
+ elementType
27
+ }) => {
28
+ const base = {
29
+ typeName,
30
+ get defaultValue() {
31
+ return getDefaultValue();
32
+ },
33
+ fill,
34
+ prune: (a) => a.map((el) => elementType.prune(el)),
35
+ validate,
36
+ is: createIsFn(validate),
37
+ cast: createCastFn(validate),
38
+ assertIs: createAssertFn(validate)
39
+ };
40
+ return base;
41
+ };
42
+
43
+ export { buildType, validateElements };
44
+ //# sourceMappingURL=build-type.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-type.mjs","sources":["../../src/array/build-type.mts"],"sourcesContent":["import { Arr, Result } from 'ts-data-forge';\nimport { type Type } from '../type.mjs';\nimport {\n createAssertFn,\n createCastFn,\n createIsFn,\n prependIndexToValidationErrors,\n type ValidationError,\n} from '../utils/index.mjs';\n\n/**\n * Validates each element of `a` against `elementType`, collecting any element\n * errors with their index prepended. Shared by the length-constrained array\n * validators.\n *\n * @internal Not part of the public package API.\n */\nexport const validateElements = <A,>(\n a: readonly unknown[],\n elementType: Type<A>,\n): Result<readonly A[], readonly ValidationError[]> => {\n const errors: readonly ValidationError[] = Arr.generate(function* () {\n for (const [index, el] of a.entries()) {\n const res = elementType.validate(el);\n\n if (Result.isErr(res)) {\n yield* prependIndexToValidationErrors(res.value, index);\n }\n }\n });\n\n if (Arr.isNonEmpty(errors)) {\n return Result.err(errors);\n }\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Result.ok(a as readonly A[]);\n};\n\n/**\n * Assembles a structural `Type<readonly A[]>` from the length-specific pieces\n * (`typeName` / `getDefaultValue` / `validate` / `fill`). Shared internally by\n * the length-constrained array validators (`fixedLengthArray` etc.) and the\n * `nonEmptyArray` validator; their outer signatures narrow the structural\n * result to the branded array type.\n *\n * @internal Not part of the public package API.\n */\nexport const buildType = <Elm, T extends readonly Elm[] = readonly Elm[]>({\n typeName,\n getDefaultValue,\n validate,\n fill,\n elementType,\n}: Readonly<{\n typeName: string;\n getDefaultValue: () => readonly Elm[];\n validate: (a: unknown) => Result<readonly Elm[], readonly ValidationError[]>;\n fill: (a: unknown) => readonly Elm[];\n elementType: Type<Elm>;\n}>): Type<T> => {\n const base: Type<readonly Elm[]> = {\n typeName,\n get defaultValue() {\n return getDefaultValue();\n },\n fill,\n prune: (a) => a.map((el) => elementType.prune(el)),\n validate,\n is: createIsFn(validate),\n cast: createCastFn(validate),\n assertIs: createAssertFn(validate),\n } as const;\n\n // The branded output type `T` (e.g. `NonEmptyArray` / `FixedLengthArray`) is\n // a subtype of the structural `readonly Elm[]` the validator actually\n // produces. The brand is guaranteed by the caller's `validate` / `fill` but\n // cannot be proven structurally, so it is asserted here once, on behalf of\n // every length-constrained array validator, instead of at each call site.\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return base as Type<T>;\n};\n"],"names":[],"mappings":";;;;;;AAiBO,MAAM,gBAAA,GAAmB,CAC9B,CAAA,EACA,WAAA,KACqD;AACrD,EAAA,MAAM,MAAA,GAAqC,GAAA,CAAI,QAAA,CAAS,aAAa;AACnE,IAAA,KAAA,MAAW,CAAC,KAAA,EAAO,EAAE,CAAA,IAAK,CAAA,CAAE,SAAQ,EAAG;AACrC,MAAA,MAAM,GAAA,GAAM,WAAA,CAAY,QAAA,CAAS,EAAE,CAAA;AAEnC,MAAA,IAAI,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,EAAG;AACrB,QAAA,OAAO,8BAAA,CAA+B,GAAA,CAAI,KAAA,EAAO,KAAK,CAAA;AAAA,MACxD;AAAA,IACF;AAAA,EACF,CAAC,CAAA;AAED,EAAA,IAAI,GAAA,CAAI,UAAA,CAAW,MAAM,CAAA,EAAG;AAC1B,IAAA,OAAO,MAAA,CAAO,IAAI,MAAM,CAAA;AAAA,EAC1B;AAGA,EAAA,OAAO,MAAA,CAAO,GAAG,CAAiB,CAAA;AACpC;AAWO,MAAM,YAAY,CAAiD;AAAA,EACxE,QAAA;AAAA,EACA,eAAA;AAAA,EACA,QAAA;AAAA,EACA,IAAA;AAAA,EACA;AACF,CAAA,KAMgB;AACd,EAAA,MAAM,IAAA,GAA6B;AAAA,IACjC,QAAA;AAAA,IACA,IAAI,YAAA,GAAe;AACjB,MAAA,OAAO,eAAA,EAAgB;AAAA,IACzB,CAAA;AAAA,IACA,IAAA;AAAA,IACA,KAAA,EAAO,CAAC,CAAA,KAAM,CAAA,CAAE,GAAA,CAAI,CAAC,EAAA,KAAO,WAAA,CAAY,KAAA,CAAM,EAAE,CAAC,CAAA;AAAA,IACjD,QAAA;AAAA,IACA,EAAA,EAAI,WAAW,QAAQ,CAAA;AAAA,IACvB,IAAA,EAAM,aAAa,QAAQ,CAAA;AAAA,IAC3B,QAAA,EAAU,eAAe,QAAQ;AAAA,GACnC;AAQA,EAAA,OAAO,IAAA;AACT;;;;"}
@@ -0,0 +1,23 @@
1
+ import { type FixedLengthArray, type SupportedLength } from 'ts-type-forge';
2
+ import { type Type } from '../type.mjs';
3
+ export type { FixedLengthArray } from 'ts-type-forge';
4
+ /**
5
+ * Creates a `Type` for a readonly array with exactly `size` elements, typed as
6
+ * the branded {@link FixedLengthArray} instead of the structural tuple type
7
+ * produced by `fixedLengthTuple`.
8
+ *
9
+ * Because the length constraint lives only in the brand, the element type is
10
+ * never expanded into tuple positions, which keeps type-checking cheap even
11
+ * when `A` is a large type. Prefer this over `fixedLengthTuple` when `A` is
12
+ * large; prefer `fixedLengthTuple` when positional element types or a literal
13
+ * `length` are needed.
14
+ */
15
+ export declare function fixedLengthArray<A, N extends SupportedLength>(size: N, elementType: Type<A>, options?: Partial<Readonly<{
16
+ typeName: string;
17
+ defaultValue: FixedLengthArray<N, A>;
18
+ }>>): Type<FixedLengthArray<N, A>>;
19
+ export declare function fixedLengthArray<A>(size: number, elementType: Type<A>, options?: Partial<Readonly<{
20
+ typeName: string;
21
+ defaultValue: readonly A[];
22
+ }>>): Type<readonly A[]>;
23
+ //# sourceMappingURL=fixed-length-array.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixed-length-array.d.mts","sourceRoot":"","sources":["../../src/array/fixed-length-array.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAOxC,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,CAAC,SAAS,eAAe,EAC3D,IAAI,EAAE,CAAC,EACP,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CACtC,CAAC,CACH,GACA,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAIhC,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC;CAC5B,CAAC,CACH,GACA,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { memoizeFunction, Arr, asUint32, Result } from 'ts-data-forge';
2
+ import { createPrimitiveValidationError } from '../utils/validation-error.mjs';
3
+ import { buildType, validateElements } from './build-type.mjs';
4
+
5
+ function fixedLengthArray(size, elementType, options) {
6
+ const typeName = options?.typeName ?? `FixedLengthArray<${size}, ${elementType.typeName}>`;
7
+ const getDefaultValue = memoizeFunction(
8
+ () => options?.defaultValue ?? Arr.create(asUint32(size), elementType.defaultValue)
9
+ );
10
+ const validate = (a) => {
11
+ if (!Arr.isArray(a)) {
12
+ return Result.err([
13
+ createPrimitiveValidationError({
14
+ actualValue: a,
15
+ expectedType: "array",
16
+ typeName,
17
+ details: void 0
18
+ })
19
+ ]);
20
+ }
21
+ if (a.length !== size) {
22
+ return Result.err([
23
+ {
24
+ path: [],
25
+ actualValue: a,
26
+ expectedType: typeName,
27
+ typeName,
28
+ details: {
29
+ kind: "array-length",
30
+ expectedLength: size,
31
+ actualLength: a.length
32
+ }
33
+ }
34
+ ]);
35
+ }
36
+ return validateElements(a, elementType);
37
+ };
38
+ const fill = (a) => Arr.isArray(a) ? Arr.map(
39
+ Arr.seq(asUint32(size)),
40
+ (i) => elementType.fill(a[i])
41
+ ) : getDefaultValue();
42
+ return buildType({ typeName, getDefaultValue, validate, fill, elementType });
43
+ }
44
+
45
+ export { fixedLengthArray };
46
+ //# sourceMappingURL=fixed-length-array.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixed-length-array.mjs","sources":["../../src/array/fixed-length-array.mts"],"sourcesContent":["import { Arr, asUint32, memoizeFunction, Result } from 'ts-data-forge';\nimport { type FixedLengthArray, type SupportedLength } from 'ts-type-forge';\nimport { type Type } from '../type.mjs';\nimport {\n createPrimitiveValidationError,\n type ValidationError,\n} from '../utils/index.mjs';\nimport { buildType, validateElements } from './build-type.mjs';\n\nexport type { FixedLengthArray } from 'ts-type-forge';\n\n/**\n * Creates a `Type` for a readonly array with exactly `size` elements, typed as\n * the branded {@link FixedLengthArray} instead of the structural tuple type\n * produced by `fixedLengthTuple`.\n *\n * Because the length constraint lives only in the brand, the element type is\n * never expanded into tuple positions, which keeps type-checking cheap even\n * when `A` is a large type. Prefer this over `fixedLengthTuple` when `A` is\n * large; prefer `fixedLengthTuple` when positional element types or a literal\n * `length` are needed.\n */\nexport function fixedLengthArray<A, N extends SupportedLength>(\n size: N,\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: FixedLengthArray<N, A>;\n }>\n >,\n): Type<FixedLengthArray<N, A>>;\n\n// For sizes outside `SupportedLength` (`0..2048`) the length cannot be encoded in the brand,\n// so the result length is left unconstrained (`readonly A[]`).\nexport function fixedLengthArray<A>(\n size: number,\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: readonly A[];\n }>\n >,\n): Type<readonly A[]>;\n\nexport function fixedLengthArray<A>(\n size: number,\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: readonly A[];\n }>\n >,\n): Type<readonly A[]> {\n type T = readonly A[];\n\n const typeName =\n options?.typeName ?? `FixedLengthArray<${size}, ${elementType.typeName}>`;\n\n const getDefaultValue = memoizeFunction(\n (): T =>\n options?.defaultValue ??\n Arr.create(asUint32(size), elementType.defaultValue),\n );\n\n const validate: Type<T>['validate'] = (a) => {\n if (!Arr.isArray(a)) {\n return Result.err([\n createPrimitiveValidationError({\n actualValue: a,\n expectedType: 'array',\n typeName,\n details: undefined,\n }),\n ]);\n }\n\n if (a.length !== size) {\n return Result.err([\n {\n path: [],\n actualValue: a,\n expectedType: typeName,\n typeName,\n details: {\n kind: 'array-length',\n expectedLength: size,\n actualLength: a.length,\n },\n } satisfies ValidationError,\n ]);\n }\n\n return validateElements(a, elementType);\n };\n\n const fill: Type<T>['fill'] = (a) =>\n Arr.isArray(a)\n ? Arr.map(\n Arr.seq(asUint32(size)),\n (i) => elementType.fill(a[i]) satisfies A,\n )\n : getDefaultValue();\n\n return buildType({ typeName, getDefaultValue, validate, fill, elementType });\n}\n"],"names":[],"mappings":";;;;AA8CO,SAAS,gBAAA,CACd,IAAA,EACA,WAAA,EACA,OAAA,EAMoB;AAGpB,EAAA,MAAM,WACJ,OAAA,EAAS,QAAA,IAAY,oBAAoB,IAAI,CAAA,EAAA,EAAK,YAAY,QAAQ,CAAA,CAAA,CAAA;AAExE,EAAA,MAAM,eAAA,GAAkB,eAAA;AAAA,IACtB,MACE,SAAS,YAAA,IACT,GAAA,CAAI,OAAO,QAAA,CAAS,IAAI,CAAA,EAAG,WAAA,CAAY,YAAY;AAAA,GACvD;AAEA,EAAA,MAAM,QAAA,GAAgC,CAAC,CAAA,KAAM;AAC3C,IAAA,IAAI,CAAC,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAA,EAAG;AACnB,MAAA,OAAO,OAAO,GAAA,CAAI;AAAA,QAChB,8BAAA,CAA+B;AAAA,UAC7B,WAAA,EAAa,CAAA;AAAA,UACb,YAAA,EAAc,OAAA;AAAA,UACd,QAAA;AAAA,UACA,OAAA,EAAS;AAAA,SACV;AAAA,OACF,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,CAAA,CAAE,WAAW,IAAA,EAAM;AACrB,MAAA,OAAO,OAAO,GAAA,CAAI;AAAA,QAChB;AAAA,UACE,MAAM,EAAC;AAAA,UACP,WAAA,EAAa,CAAA;AAAA,UACb,YAAA,EAAc,QAAA;AAAA,UACd,QAAA;AAAA,UACA,OAAA,EAAS;AAAA,YACP,IAAA,EAAM,cAAA;AAAA,YACN,cAAA,EAAgB,IAAA;AAAA,YAChB,cAAc,CAAA,CAAE;AAAA;AAClB;AACF,OACD,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,gBAAA,CAAiB,GAAG,WAAW,CAAA;AAAA,EACxC,CAAA;AAEA,EAAA,MAAM,OAAwB,CAAC,CAAA,KAC7B,IAAI,OAAA,CAAQ,CAAC,IACT,GAAA,CAAI,GAAA;AAAA,IACF,GAAA,CAAI,GAAA,CAAI,QAAA,CAAS,IAAI,CAAC,CAAA;AAAA,IACtB,CAAC,CAAA,KAAM,WAAA,CAAY,IAAA,CAAK,CAAA,CAAE,CAAC,CAAC;AAAA,MAE9B,eAAA,EAAgB;AAEtB,EAAA,OAAO,UAAU,EAAE,QAAA,EAAU,iBAAiB,QAAA,EAAU,IAAA,EAAM,aAAa,CAAA;AAC7E;;;;"}
@@ -1,8 +1,11 @@
1
1
  export * from './array.mjs';
2
+ export * from './bounded-length-array.mjs';
2
3
  export * from './bounded-length-tuple.mjs';
4
+ export * from './fixed-length-array.mjs';
3
5
  export * from './fixed-length-tuple.mjs';
4
- export * from './length-constrained-array.mjs';
6
+ export * from './max-length-array.mjs';
5
7
  export * from './max-length-tuple.mjs';
8
+ export * from './min-length-array.mjs';
6
9
  export * from './min-length-tuple.mjs';
7
10
  export * from './non-empty-array.mjs';
8
11
  export * from './tuple.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/array/index.mts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/array/index.mts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,4BAA4B,CAAC;AAC3C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC"}
@@ -1,8 +1,11 @@
1
1
  export { array } from './array.mjs';
2
+ export { boundedLengthArray } from './bounded-length-array.mjs';
2
3
  export { boundedLengthTuple } from './bounded-length-tuple.mjs';
4
+ export { fixedLengthArray } from './fixed-length-array.mjs';
3
5
  export { fixedLengthTuple } from './fixed-length-tuple.mjs';
4
- export { boundedLengthArray, fixedLengthArray, maxLengthArray, minLengthArray } from './length-constrained-array.mjs';
6
+ export { maxLengthArray } from './max-length-array.mjs';
5
7
  export { maxLengthTuple } from './max-length-tuple.mjs';
8
+ export { minLengthArray } from './min-length-array.mjs';
6
9
  export { minLengthTuple } from './min-length-tuple.mjs';
7
10
  export { nonEmptyArray } from './non-empty-array.mjs';
8
11
  export { tuple } from './tuple.mjs';
@@ -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,21 @@
1
+ import { type MaxLengthArray, type SupportedLength } from 'ts-type-forge';
2
+ import { type Type } from '../type.mjs';
3
+ export type { MaxLengthArray } from 'ts-type-forge';
4
+ /**
5
+ * Creates a `Type` for a readonly array with at most `maxLength` elements,
6
+ * typed as the branded {@link MaxLengthArray} instead of the union of tuple
7
+ * types produced by `maxLengthTuple`.
8
+ *
9
+ * Because the length constraint lives only in the brand, no union of tuples
10
+ * of the element type is ever constructed, which keeps type-checking cheap
11
+ * even when `A` is a large type.
12
+ */
13
+ export declare function maxLengthArray<A, N extends SupportedLength>(maxLength: N, elementType: Type<A>, options?: Partial<Readonly<{
14
+ typeName: string;
15
+ defaultValue: MaxLengthArray<N, A>;
16
+ }>>): Type<MaxLengthArray<N, A>>;
17
+ export declare function maxLengthArray<A>(maxLength: number, elementType: Type<A>, options?: Partial<Readonly<{
18
+ typeName: string;
19
+ defaultValue: readonly A[];
20
+ }>>): Type<readonly A[]>;
21
+ //# sourceMappingURL=max-length-array.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"max-length-array.d.mts","sourceRoot":"","sources":["../../src/array/max-length-array.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAOxC,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,CAAC,SAAS,eAAe,EACzD,SAAS,EAAE,CAAC,EACZ,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CACpC,CAAC,CACH,GACA,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAI9B,wBAAgB,cAAc,CAAC,CAAC,EAC9B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC;CAC5B,CAAC,CACH,GACA,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC"}
@@ -0,0 +1,50 @@
1
+ import { memoizeFunction, Arr, Result, asUint32 } from 'ts-data-forge';
2
+ import { createPrimitiveValidationError } from '../utils/validation-error.mjs';
3
+ import { buildType, validateElements } from './build-type.mjs';
4
+
5
+ function maxLengthArray(maxLength, elementType, options) {
6
+ const typeName = options?.typeName ?? `MaxLengthArray<${maxLength}, ${elementType.typeName}>`;
7
+ const getDefaultValue = memoizeFunction(
8
+ () => options?.defaultValue ?? // The empty array is the shortest value satisfying `length <= maxLength`.
9
+ Arr.create(0, elementType.defaultValue)
10
+ );
11
+ const validate = (a) => {
12
+ if (!Arr.isArray(a)) {
13
+ return Result.err([
14
+ createPrimitiveValidationError({
15
+ actualValue: a,
16
+ expectedType: "array",
17
+ typeName,
18
+ details: void 0
19
+ })
20
+ ]);
21
+ }
22
+ if (a.length > maxLength) {
23
+ return Result.err([
24
+ {
25
+ path: [],
26
+ actualValue: a,
27
+ expectedType: typeName,
28
+ typeName,
29
+ details: {
30
+ kind: "array-max-length",
31
+ maxLength,
32
+ actualLength: a.length
33
+ }
34
+ }
35
+ ]);
36
+ }
37
+ return validateElements(a, elementType);
38
+ };
39
+ const fill = (a) => Arr.isArray(a) ? (
40
+ // Keep the input but trim down to at most `maxLength` elements.
41
+ Arr.map(
42
+ Arr.take(a, asUint32(maxLength)),
43
+ (el) => elementType.fill(el)
44
+ )
45
+ ) : getDefaultValue();
46
+ return buildType({ typeName, getDefaultValue, validate, fill, elementType });
47
+ }
48
+
49
+ export { maxLengthArray };
50
+ //# sourceMappingURL=max-length-array.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"max-length-array.mjs","sources":["../../src/array/max-length-array.mts"],"sourcesContent":["import { Arr, asUint32, memoizeFunction, Result } from 'ts-data-forge';\nimport { type MaxLengthArray, type SupportedLength } from 'ts-type-forge';\nimport { type Type } from '../type.mjs';\nimport {\n createPrimitiveValidationError,\n type ValidationError,\n} from '../utils/index.mjs';\nimport { buildType, validateElements } from './build-type.mjs';\n\nexport type { MaxLengthArray } from 'ts-type-forge';\n\n/**\n * Creates a `Type` for a readonly array with at most `maxLength` elements,\n * typed as the branded {@link MaxLengthArray} instead of the union of tuple\n * types produced by `maxLengthTuple`.\n *\n * Because the length constraint lives only in the brand, no union of tuples\n * of the element type is ever constructed, which keeps type-checking cheap\n * even when `A` is a large type.\n */\nexport function maxLengthArray<A, N extends SupportedLength>(\n maxLength: N,\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: MaxLengthArray<N, A>;\n }>\n >,\n): Type<MaxLengthArray<N, A>>;\n\n// For bounds outside `SupportedLength` (`0..2048`) the length cannot be encoded in the brand,\n// so the result length is left unconstrained (`readonly A[]`).\nexport function maxLengthArray<A>(\n maxLength: number,\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: readonly A[];\n }>\n >,\n): Type<readonly A[]>;\n\nexport function maxLengthArray<A>(\n maxLength: number,\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: readonly A[];\n }>\n >,\n): Type<readonly A[]> {\n type T = readonly A[];\n\n const typeName =\n options?.typeName ??\n `MaxLengthArray<${maxLength}, ${elementType.typeName}>`;\n\n const getDefaultValue = memoizeFunction(\n (): T =>\n options?.defaultValue ??\n // The empty array is the shortest value satisfying `length <= maxLength`.\n Arr.create(0, elementType.defaultValue),\n );\n\n const validate: Type<T>['validate'] = (a) => {\n if (!Arr.isArray(a)) {\n return Result.err([\n createPrimitiveValidationError({\n actualValue: a,\n expectedType: 'array',\n typeName,\n details: undefined,\n }),\n ]);\n }\n\n if (a.length > maxLength) {\n return Result.err([\n {\n path: [],\n actualValue: a,\n expectedType: typeName,\n typeName,\n details: {\n kind: 'array-max-length',\n maxLength,\n actualLength: a.length,\n },\n } satisfies ValidationError,\n ]);\n }\n\n return validateElements(a, elementType);\n };\n\n const fill: Type<T>['fill'] = (a) =>\n Arr.isArray(a)\n ? // Keep the input but trim down to at most `maxLength` elements.\n Arr.map(\n Arr.take(a, asUint32(maxLength)),\n (el) => elementType.fill(el) satisfies A,\n )\n : getDefaultValue();\n\n return buildType({ typeName, getDefaultValue, validate, fill, elementType });\n}\n"],"names":[],"mappings":";;;;AA4CO,SAAS,cAAA,CACd,SAAA,EACA,WAAA,EACA,OAAA,EAMoB;AAGpB,EAAA,MAAM,WACJ,OAAA,EAAS,QAAA,IACT,kBAAkB,SAAS,CAAA,EAAA,EAAK,YAAY,QAAQ,CAAA,CAAA,CAAA;AAEtD,EAAA,MAAM,eAAA,GAAkB,eAAA;AAAA,IACtB,MACE,OAAA,EAAS,YAAA;AAAA,IAET,GAAA,CAAI,MAAA,CAAO,CAAA,EAAG,WAAA,CAAY,YAAY;AAAA,GAC1C;AAEA,EAAA,MAAM,QAAA,GAAgC,CAAC,CAAA,KAAM;AAC3C,IAAA,IAAI,CAAC,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAA,EAAG;AACnB,MAAA,OAAO,OAAO,GAAA,CAAI;AAAA,QAChB,8BAAA,CAA+B;AAAA,UAC7B,WAAA,EAAa,CAAA;AAAA,UACb,YAAA,EAAc,OAAA;AAAA,UACd,QAAA;AAAA,UACA,OAAA,EAAS;AAAA,SACV;AAAA,OACF,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,CAAA,CAAE,SAAS,SAAA,EAAW;AACxB,MAAA,OAAO,OAAO,GAAA,CAAI;AAAA,QAChB;AAAA,UACE,MAAM,EAAC;AAAA,UACP,WAAA,EAAa,CAAA;AAAA,UACb,YAAA,EAAc,QAAA;AAAA,UACd,QAAA;AAAA,UACA,OAAA,EAAS;AAAA,YACP,IAAA,EAAM,kBAAA;AAAA,YACN,SAAA;AAAA,YACA,cAAc,CAAA,CAAE;AAAA;AAClB;AACF,OACD,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,gBAAA,CAAiB,GAAG,WAAW,CAAA;AAAA,EACxC,CAAA;AAEA,EAAA,MAAM,IAAA,GAAwB,CAAC,CAAA,KAC7B,GAAA,CAAI,QAAQ,CAAC,CAAA;AAAA;AAAA,IAET,GAAA,CAAI,GAAA;AAAA,MACF,GAAA,CAAI,IAAA,CAAK,CAAA,EAAG,QAAA,CAAS,SAAS,CAAC,CAAA;AAAA,MAC/B,CAAC,EAAA,KAAO,WAAA,CAAY,IAAA,CAAK,EAAE;AAAA;AAC7B,MACA,eAAA,EAAgB;AAEtB,EAAA,OAAO,UAAU,EAAE,QAAA,EAAU,iBAAiB,QAAA,EAAU,IAAA,EAAM,aAAa,CAAA;AAC7E;;;;"}
@@ -0,0 +1,21 @@
1
+ import { type MinLengthArray, type SupportedLength } from 'ts-type-forge';
2
+ import { type Type } from '../type.mjs';
3
+ export type { MinLengthArray } from 'ts-type-forge';
4
+ /**
5
+ * Creates a `Type` for a readonly array with at least `minLength` elements,
6
+ * typed as the branded {@link MinLengthArray} instead of the structural
7
+ * `readonly [A, ..., A, ...A[]]` type produced by `minLengthTuple`.
8
+ *
9
+ * Because the length constraint lives only in the brand, the element type is
10
+ * never expanded into tuple positions, which keeps type-checking cheap even
11
+ * when `A` is a large type.
12
+ */
13
+ export declare function minLengthArray<A, N extends SupportedLength>(minLength: N, elementType: Type<A>, options?: Partial<Readonly<{
14
+ typeName: string;
15
+ defaultValue: MinLengthArray<N, A>;
16
+ }>>): Type<MinLengthArray<N, A>>;
17
+ export declare function minLengthArray<A>(minLength: number, elementType: Type<A>, options?: Partial<Readonly<{
18
+ typeName: string;
19
+ defaultValue: readonly A[];
20
+ }>>): Type<readonly A[]>;
21
+ //# sourceMappingURL=min-length-array.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"min-length-array.d.mts","sourceRoot":"","sources":["../../src/array/min-length-array.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAOxC,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,CAAC,SAAS,eAAe,EACzD,SAAS,EAAE,CAAC,EACZ,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CACpC,CAAC,CACH,GACA,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAI9B,wBAAgB,cAAc,CAAC,CAAC,EAC9B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC,EACpB,OAAO,CAAC,EAAE,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,SAAS,CAAC,EAAE,CAAC;CAC5B,CAAC,CACH,GACA,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { memoizeFunction, Arr, asUint32, Result } from 'ts-data-forge';
2
+ import { createPrimitiveValidationError } from '../utils/validation-error.mjs';
3
+ import { buildType, validateElements } from './build-type.mjs';
4
+
5
+ function minLengthArray(minLength, elementType, options) {
6
+ const typeName = options?.typeName ?? `MinLengthArray<${minLength}, ${elementType.typeName}>`;
7
+ const getDefaultValue = memoizeFunction(
8
+ () => options?.defaultValue ?? // An array of `minLength` elements is the shortest value satisfying the bound.
9
+ Arr.create(asUint32(minLength), elementType.defaultValue)
10
+ );
11
+ const validate = (a) => {
12
+ if (!Arr.isArray(a)) {
13
+ return Result.err([
14
+ createPrimitiveValidationError({
15
+ actualValue: a,
16
+ expectedType: "array",
17
+ typeName,
18
+ details: void 0
19
+ })
20
+ ]);
21
+ }
22
+ if (a.length < minLength) {
23
+ return Result.err([
24
+ {
25
+ path: [],
26
+ actualValue: a,
27
+ expectedType: typeName,
28
+ typeName,
29
+ details: {
30
+ kind: "array-min-length",
31
+ minLength,
32
+ actualLength: a.length
33
+ }
34
+ }
35
+ ]);
36
+ }
37
+ return validateElements(a, elementType);
38
+ };
39
+ const fill = (a) => {
40
+ if (!Arr.isArray(a)) {
41
+ return getDefaultValue();
42
+ }
43
+ return a.length >= minLength ? Arr.map(a, (el) => elementType.fill(el)) : Arr.map(
44
+ Arr.seq(asUint32(minLength)),
45
+ (i) => elementType.fill(a[i])
46
+ );
47
+ };
48
+ return buildType({ typeName, getDefaultValue, validate, fill, elementType });
49
+ }
50
+
51
+ export { minLengthArray };
52
+ //# sourceMappingURL=min-length-array.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"min-length-array.mjs","sources":["../../src/array/min-length-array.mts"],"sourcesContent":["import { Arr, asUint32, memoizeFunction, Result } from 'ts-data-forge';\nimport { type MinLengthArray, type SupportedLength } from 'ts-type-forge';\nimport { type Type } from '../type.mjs';\nimport {\n createPrimitiveValidationError,\n type ValidationError,\n} from '../utils/index.mjs';\nimport { buildType, validateElements } from './build-type.mjs';\n\nexport type { MinLengthArray } from 'ts-type-forge';\n\n/**\n * Creates a `Type` for a readonly array with at least `minLength` elements,\n * typed as the branded {@link MinLengthArray} instead of the structural\n * `readonly [A, ..., A, ...A[]]` type produced by `minLengthTuple`.\n *\n * Because the length constraint lives only in the brand, the element type is\n * never expanded into tuple positions, which keeps type-checking cheap even\n * when `A` is a large type.\n */\nexport function minLengthArray<A, N extends SupportedLength>(\n minLength: N,\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: MinLengthArray<N, A>;\n }>\n >,\n): Type<MinLengthArray<N, A>>;\n\n// For bounds outside `SupportedLength` (`0..2048`) the length cannot be encoded in the brand,\n// so the result length is left unconstrained (`readonly A[]`).\nexport function minLengthArray<A>(\n minLength: number,\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: readonly A[];\n }>\n >,\n): Type<readonly A[]>;\n\nexport function minLengthArray<A>(\n minLength: number,\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: readonly A[];\n }>\n >,\n): Type<readonly A[]> {\n type T = readonly A[];\n\n const typeName =\n options?.typeName ??\n `MinLengthArray<${minLength}, ${elementType.typeName}>`;\n\n const getDefaultValue = memoizeFunction(\n (): T =>\n options?.defaultValue ??\n // An array of `minLength` elements is the shortest value satisfying the bound.\n Arr.create(asUint32(minLength), elementType.defaultValue),\n );\n\n const validate: Type<T>['validate'] = (a) => {\n if (!Arr.isArray(a)) {\n return Result.err([\n createPrimitiveValidationError({\n actualValue: a,\n expectedType: 'array',\n typeName,\n details: undefined,\n }),\n ]);\n }\n\n if (a.length < minLength) {\n return Result.err([\n {\n path: [],\n actualValue: a,\n expectedType: typeName,\n typeName,\n details: {\n kind: 'array-min-length',\n minLength,\n actualLength: a.length,\n },\n } satisfies ValidationError,\n ]);\n }\n\n return validateElements(a, elementType);\n };\n\n const fill: Type<T>['fill'] = (a) => {\n if (!Arr.isArray(a)) {\n return getDefaultValue();\n }\n\n // Keep the input if it is long enough; otherwise pad up to `minLength`.\n return a.length >= minLength\n ? Arr.map(a, (el) => elementType.fill(el) satisfies A)\n : Arr.map(\n Arr.seq(asUint32(minLength)),\n (i) => elementType.fill(a[i]) satisfies A,\n );\n };\n\n return buildType({ typeName, getDefaultValue, validate, fill, elementType });\n}\n"],"names":[],"mappings":";;;;AA4CO,SAAS,cAAA,CACd,SAAA,EACA,WAAA,EACA,OAAA,EAMoB;AAGpB,EAAA,MAAM,WACJ,OAAA,EAAS,QAAA,IACT,kBAAkB,SAAS,CAAA,EAAA,EAAK,YAAY,QAAQ,CAAA,CAAA,CAAA;AAEtD,EAAA,MAAM,eAAA,GAAkB,eAAA;AAAA,IACtB,MACE,OAAA,EAAS,YAAA;AAAA,IAET,IAAI,MAAA,CAAO,QAAA,CAAS,SAAS,CAAA,EAAG,YAAY,YAAY;AAAA,GAC5D;AAEA,EAAA,MAAM,QAAA,GAAgC,CAAC,CAAA,KAAM;AAC3C,IAAA,IAAI,CAAC,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAA,EAAG;AACnB,MAAA,OAAO,OAAO,GAAA,CAAI;AAAA,QAChB,8BAAA,CAA+B;AAAA,UAC7B,WAAA,EAAa,CAAA;AAAA,UACb,YAAA,EAAc,OAAA;AAAA,UACd,QAAA;AAAA,UACA,OAAA,EAAS;AAAA,SACV;AAAA,OACF,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,CAAA,CAAE,SAAS,SAAA,EAAW;AACxB,MAAA,OAAO,OAAO,GAAA,CAAI;AAAA,QAChB;AAAA,UACE,MAAM,EAAC;AAAA,UACP,WAAA,EAAa,CAAA;AAAA,UACb,YAAA,EAAc,QAAA;AAAA,UACd,QAAA;AAAA,UACA,OAAA,EAAS;AAAA,YACP,IAAA,EAAM,kBAAA;AAAA,YACN,SAAA;AAAA,YACA,cAAc,CAAA,CAAE;AAAA;AAClB;AACF,OACD,CAAA;AAAA,IACH;AAEA,IAAA,OAAO,gBAAA,CAAiB,GAAG,WAAW,CAAA;AAAA,EACxC,CAAA;AAEA,EAAA,MAAM,IAAA,GAAwB,CAAC,CAAA,KAAM;AACnC,IAAA,IAAI,CAAC,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAA,EAAG;AACnB,MAAA,OAAO,eAAA,EAAgB;AAAA,IACzB;AAGA,IAAA,OAAO,CAAA,CAAE,MAAA,IAAU,SAAA,GACf,GAAA,CAAI,GAAA,CAAI,CAAA,EAAG,CAAC,EAAA,KAAO,WAAA,CAAY,IAAA,CAAK,EAAE,CAAa,IACnD,GAAA,CAAI,GAAA;AAAA,MACF,GAAA,CAAI,GAAA,CAAI,QAAA,CAAS,SAAS,CAAC,CAAA;AAAA,MAC3B,CAAC,CAAA,KAAM,WAAA,CAAY,IAAA,CAAK,CAAA,CAAE,CAAC,CAAC;AAAA,KAC9B;AAAA,EACN,CAAA;AAEA,EAAA,OAAO,UAAU,EAAE,QAAA,EAAU,iBAAiB,QAAA,EAAU,IAAA,EAAM,aAAa,CAAA;AAC7E;;;;"}
@@ -1,8 +1,8 @@
1
- import { type NonEmptyArray } from 'ts-type-forge';
1
+ import { type NonEmptyArray, type NonEmptyTuple } from 'ts-type-forge';
2
2
  import { type Type } from '../type.mjs';
3
3
  export type { NonEmptyArray } from 'ts-type-forge';
4
4
  export declare const nonEmptyArray: <A>(elementType: Type<A>, options?: Partial<Readonly<{
5
5
  typeName: string;
6
- defaultValue: NonEmptyArray<A>;
6
+ defaultValue: NonEmptyTuple<A>;
7
7
  }>>) => Type<NonEmptyArray<A>>;
8
8
  //# sourceMappingURL=non-empty-array.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"non-empty-array.d.mts","sourceRoot":"","sources":["../../src/array/non-empty-array.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAUxC,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,eAAO,MAAM,aAAa,GAAI,CAAC,eAChB,IAAI,CAAC,CAAC,CAAC,YACV,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;CAChC,CAAC,CACH,KACA,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAyEvB,CAAC"}
1
+ {"version":3,"file":"non-empty-array.d.mts","sourceRoot":"","sources":["../../src/array/non-empty-array.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAQxC,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEnD,eAAO,MAAM,aAAa,GAAI,CAAC,eAChB,IAAI,CAAC,CAAC,CAAC,YACV,OAAO,CACf,QAAQ,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;CAChC,CAAC,CACH,KACA,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAmEvB,CAAC"}
@@ -1,8 +1,6 @@
1
1
  import { memoizeFunction, Arr, Result } from 'ts-data-forge';
2
- import { createAssertFn } from '../utils/create-assert-fn.mjs';
3
- import { createCastFn } from '../utils/create-cast-fn.mjs';
4
- import { createIsFn } from '../utils/create-is-fn.mjs';
5
2
  import { createPrimitiveValidationError, prependIndexToValidationErrors } from '../utils/validation-error.mjs';
3
+ import { buildType } from './build-type.mjs';
6
4
 
7
5
  const nonEmptyArray = (elementType, options) => {
8
6
  const typeName = options?.typeName ?? `NonEmptyArray<${elementType.typeName}>`;
@@ -46,20 +44,14 @@ const nonEmptyArray = (elementType, options) => {
46
44
  }
47
45
  return Result.ok(a);
48
46
  };
49
- const fill = (a) => Arr.isArray(a) && Arr.isNonEmpty(a) ? Arr.map(a, (e) => elementType.fill(e)) : getDefaultValue();
50
- const prune = (a) => Arr.map(a, (e) => elementType.prune(e));
51
- return {
47
+ const fill = (a) => Arr.isArray(a) && Arr.isMinLengthTuple(a, 1) ? Arr.map(a, (e) => elementType.fill(e)) : getDefaultValue();
48
+ return buildType({
52
49
  typeName,
53
- get defaultValue() {
54
- return getDefaultValue();
55
- },
56
- fill,
57
- prune,
50
+ getDefaultValue,
58
51
  validate,
59
- is: createIsFn(validate),
60
- assertIs: createAssertFn(validate),
61
- cast: createCastFn(validate)
62
- };
52
+ fill,
53
+ elementType
54
+ });
63
55
  };
64
56
 
65
57
  export { nonEmptyArray };
@@ -1 +1 @@
1
- {"version":3,"file":"non-empty-array.mjs","sources":["../../src/array/non-empty-array.mts"],"sourcesContent":["import { Arr, memoizeFunction, Result } from 'ts-data-forge';\nimport { type NonEmptyArray } from 'ts-type-forge';\nimport { type Type } from '../type.mjs';\nimport {\n createAssertFn,\n createCastFn,\n createIsFn,\n createPrimitiveValidationError,\n prependIndexToValidationErrors,\n type ValidationError,\n} from '../utils/index.mjs';\n\nexport type { NonEmptyArray } from 'ts-type-forge';\n\nexport const nonEmptyArray = <A,>(\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: NonEmptyArray<A>;\n }>\n >,\n): Type<NonEmptyArray<A>> => {\n type T = NonEmptyArray<A>;\n\n const typeName =\n options?.typeName ?? `NonEmptyArray<${elementType.typeName}>`;\n\n const getDefaultValue = memoizeFunction(\n (): T => options?.defaultValue ?? Arr.newArray(1, elementType.defaultValue),\n );\n\n const validate: Type<T>['validate'] = (a) => {\n if (!Arr.isArray(a)) {\n return Result.err([\n createPrimitiveValidationError({\n actualValue: a,\n expectedType: 'array',\n typeName,\n details: undefined,\n }),\n ]);\n }\n\n if (Arr.isEmpty(a)) {\n return Result.err([\n {\n path: [],\n actualValue: a,\n expectedType: typeName,\n typeName,\n details: {\n kind: 'non-empty-array',\n },\n } satisfies ValidationError,\n ]);\n }\n\n const errors: readonly ValidationError[] = Arr.generate(function* () {\n for (const [index, el] of a.entries()) {\n const res = elementType.validate(el);\n\n if (Result.isErr(res)) {\n yield* prependIndexToValidationErrors(res.value, index);\n }\n }\n });\n\n if (Arr.isNonEmpty(errors)) {\n return Result.err(errors);\n }\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Result.ok(a as unknown as T);\n };\n\n const fill: Type<T>['fill'] = (a) =>\n Arr.isArray(a) && Arr.isNonEmpty(a)\n ? Arr.map(a, (e) => elementType.fill(e))\n : getDefaultValue();\n\n const prune = (a: T): T => Arr.map(a, (e) => elementType.prune(e));\n\n return {\n typeName,\n get defaultValue() {\n return getDefaultValue();\n },\n fill,\n prune,\n validate,\n is: createIsFn(validate),\n assertIs: createAssertFn(validate),\n cast: createCastFn(validate),\n };\n};\n"],"names":[],"mappings":";;;;;;AAcO,MAAM,aAAA,GAAgB,CAC3B,WAAA,EACA,OAAA,KAM2B;AAG3B,EAAA,MAAM,QAAA,GACJ,OAAA,EAAS,QAAA,IAAY,CAAA,cAAA,EAAiB,YAAY,QAAQ,CAAA,CAAA,CAAA;AAE5D,EAAA,MAAM,eAAA,GAAkB,eAAA;AAAA,IACtB,MAAS,OAAA,EAAS,YAAA,IAAgB,IAAI,QAAA,CAAS,CAAA,EAAG,YAAY,YAAY;AAAA,GAC5E;AAEA,EAAA,MAAM,QAAA,GAAgC,CAAC,CAAA,KAAM;AAC3C,IAAA,IAAI,CAAC,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAA,EAAG;AACnB,MAAA,OAAO,OAAO,GAAA,CAAI;AAAA,QAChB,8BAAA,CAA+B;AAAA,UAC7B,WAAA,EAAa,CAAA;AAAA,UACb,YAAA,EAAc,OAAA;AAAA,UACd,QAAA;AAAA,UACA,OAAA,EAAS;AAAA,SACV;AAAA,OACF,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAA,EAAG;AAClB,MAAA,OAAO,OAAO,GAAA,CAAI;AAAA,QAChB;AAAA,UACE,MAAM,EAAC;AAAA,UACP,WAAA,EAAa,CAAA;AAAA,UACb,YAAA,EAAc,QAAA;AAAA,UACd,QAAA;AAAA,UACA,OAAA,EAAS;AAAA,YACP,IAAA,EAAM;AAAA;AACR;AACF,OACD,CAAA;AAAA,IACH;AAEA,IAAA,MAAM,MAAA,GAAqC,GAAA,CAAI,QAAA,CAAS,aAAa;AACnE,MAAA,KAAA,MAAW,CAAC,KAAA,EAAO,EAAE,CAAA,IAAK,CAAA,CAAE,SAAQ,EAAG;AACrC,QAAA,MAAM,GAAA,GAAM,WAAA,CAAY,QAAA,CAAS,EAAE,CAAA;AAEnC,QAAA,IAAI,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,EAAG;AACrB,UAAA,OAAO,8BAAA,CAA+B,GAAA,CAAI,KAAA,EAAO,KAAK,CAAA;AAAA,QACxD;AAAA,MACF;AAAA,IACF,CAAC,CAAA;AAED,IAAA,IAAI,GAAA,CAAI,UAAA,CAAW,MAAM,CAAA,EAAG;AAC1B,MAAA,OAAO,MAAA,CAAO,IAAI,MAAM,CAAA;AAAA,IAC1B;AAGA,IAAA,OAAO,MAAA,CAAO,GAAG,CAAiB,CAAA;AAAA,EACpC,CAAA;AAEA,EAAA,MAAM,IAAA,GAAwB,CAAC,CAAA,KAC7B,GAAA,CAAI,QAAQ,CAAC,CAAA,IAAK,IAAI,UAAA,CAAW,CAAC,IAC9B,GAAA,CAAI,GAAA,CAAI,GAAG,CAAC,CAAA,KAAM,YAAY,IAAA,CAAK,CAAC,CAAC,CAAA,GACrC,eAAA,EAAgB;AAEtB,EAAA,MAAM,KAAA,GAAQ,CAAC,CAAA,KAAY,GAAA,CAAI,GAAA,CAAI,CAAA,EAAG,CAAC,CAAA,KAAM,WAAA,CAAY,KAAA,CAAM,CAAC,CAAC,CAAA;AAEjE,EAAA,OAAO;AAAA,IACL,QAAA;AAAA,IACA,IAAI,YAAA,GAAe;AACjB,MAAA,OAAO,eAAA,EAAgB;AAAA,IACzB,CAAA;AAAA,IACA,IAAA;AAAA,IACA,KAAA;AAAA,IACA,QAAA;AAAA,IACA,EAAA,EAAI,WAAW,QAAQ,CAAA;AAAA,IACvB,QAAA,EAAU,eAAe,QAAQ,CAAA;AAAA,IACjC,IAAA,EAAM,aAAa,QAAQ;AAAA,GAC7B;AACF;;;;"}
1
+ {"version":3,"file":"non-empty-array.mjs","sources":["../../src/array/non-empty-array.mts"],"sourcesContent":["import { Arr, memoizeFunction, Result } from 'ts-data-forge';\nimport { type NonEmptyArray, type NonEmptyTuple } from 'ts-type-forge';\nimport { type Type } from '../type.mjs';\nimport {\n createPrimitiveValidationError,\n prependIndexToValidationErrors,\n type ValidationError,\n} from '../utils/index.mjs';\nimport { buildType } from './build-type.mjs';\n\nexport type { NonEmptyArray } from 'ts-type-forge';\n\nexport const nonEmptyArray = <A,>(\n elementType: Type<A>,\n options?: Partial<\n Readonly<{\n typeName: string;\n defaultValue: NonEmptyTuple<A>;\n }>\n >,\n): Type<NonEmptyArray<A>> => {\n const typeName =\n options?.typeName ?? `NonEmptyArray<${elementType.typeName}>`;\n\n const getDefaultValue = memoizeFunction(\n (): readonly A[] =>\n options?.defaultValue ?? Arr.newArray(1, elementType.defaultValue),\n );\n\n const validate = (\n a: unknown,\n ): Result<readonly A[], readonly ValidationError[]> => {\n if (!Arr.isArray(a)) {\n return Result.err([\n createPrimitiveValidationError({\n actualValue: a,\n expectedType: 'array',\n typeName,\n details: undefined,\n }),\n ]);\n }\n\n if (Arr.isEmpty(a)) {\n return Result.err([\n {\n path: [],\n actualValue: a,\n expectedType: typeName,\n typeName,\n details: {\n kind: 'non-empty-array',\n },\n } satisfies ValidationError,\n ]);\n }\n\n const errors: readonly ValidationError[] = Arr.generate(function* () {\n for (const [index, el] of a.entries()) {\n const res = elementType.validate(el);\n\n if (Result.isErr(res)) {\n yield* prependIndexToValidationErrors(res.value, index);\n }\n }\n });\n\n if (Arr.isNonEmpty(errors)) {\n return Result.err(errors);\n }\n\n // eslint-disable-next-line total-functions/no-unsafe-type-assertion\n return Result.ok(a as readonly A[]);\n };\n\n const fill = (a: unknown): readonly A[] =>\n Arr.isArray(a) && Arr.isMinLengthTuple(a, 1)\n ? Arr.map(a, (e) => elementType.fill(e) satisfies A)\n : getDefaultValue();\n\n return buildType<A, NonEmptyArray<A>>({\n typeName,\n getDefaultValue,\n validate,\n fill,\n elementType,\n });\n};\n"],"names":[],"mappings":";;;;AAYO,MAAM,aAAA,GAAgB,CAC3B,WAAA,EACA,OAAA,KAM2B;AAC3B,EAAA,MAAM,QAAA,GACJ,OAAA,EAAS,QAAA,IAAY,CAAA,cAAA,EAAiB,YAAY,QAAQ,CAAA,CAAA,CAAA;AAE5D,EAAA,MAAM,eAAA,GAAkB,eAAA;AAAA,IACtB,MACE,OAAA,EAAS,YAAA,IAAgB,IAAI,QAAA,CAAS,CAAA,EAAG,YAAY,YAAY;AAAA,GACrE;AAEA,EAAA,MAAM,QAAA,GAAW,CACf,CAAA,KACqD;AACrD,IAAA,IAAI,CAAC,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAA,EAAG;AACnB,MAAA,OAAO,OAAO,GAAA,CAAI;AAAA,QAChB,8BAAA,CAA+B;AAAA,UAC7B,WAAA,EAAa,CAAA;AAAA,UACb,YAAA,EAAc,OAAA;AAAA,UACd,QAAA;AAAA,UACA,OAAA,EAAS;AAAA,SACV;AAAA,OACF,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAA,EAAG;AAClB,MAAA,OAAO,OAAO,GAAA,CAAI;AAAA,QAChB;AAAA,UACE,MAAM,EAAC;AAAA,UACP,WAAA,EAAa,CAAA;AAAA,UACb,YAAA,EAAc,QAAA;AAAA,UACd,QAAA;AAAA,UACA,OAAA,EAAS;AAAA,YACP,IAAA,EAAM;AAAA;AACR;AACF,OACD,CAAA;AAAA,IACH;AAEA,IAAA,MAAM,MAAA,GAAqC,GAAA,CAAI,QAAA,CAAS,aAAa;AACnE,MAAA,KAAA,MAAW,CAAC,KAAA,EAAO,EAAE,CAAA,IAAK,CAAA,CAAE,SAAQ,EAAG;AACrC,QAAA,MAAM,GAAA,GAAM,WAAA,CAAY,QAAA,CAAS,EAAE,CAAA;AAEnC,QAAA,IAAI,MAAA,CAAO,KAAA,CAAM,GAAG,CAAA,EAAG;AACrB,UAAA,OAAO,8BAAA,CAA+B,GAAA,CAAI,KAAA,EAAO,KAAK,CAAA;AAAA,QACxD;AAAA,MACF;AAAA,IACF,CAAC,CAAA;AAED,IAAA,IAAI,GAAA,CAAI,UAAA,CAAW,MAAM,CAAA,EAAG;AAC1B,MAAA,OAAO,MAAA,CAAO,IAAI,MAAM,CAAA;AAAA,IAC1B;AAGA,IAAA,OAAO,MAAA,CAAO,GAAG,CAAiB,CAAA;AAAA,EACpC,CAAA;AAEA,EAAA,MAAM,IAAA,GAAO,CAAC,CAAA,KACZ,GAAA,CAAI,QAAQ,CAAC,CAAA,IAAK,GAAA,CAAI,gBAAA,CAAiB,CAAA,EAAG,CAAC,IACvC,GAAA,CAAI,GAAA,CAAI,GAAG,CAAC,CAAA,KAAM,YAAY,IAAA,CAAK,CAAC,CAAa,CAAA,GACjD,eAAA,EAAgB;AAEtB,EAAA,OAAO,SAAA,CAA+B;AAAA,IACpC,QAAA;AAAA,IACA,eAAA;AAAA,IACA,QAAA;AAAA,IACA,IAAA;AAAA,IACA;AAAA,GACD,CAAA;AACH;;;;"}
@@ -1,13 +1,13 @@
1
- import { type Intersection, type NonEmptyArray } from 'ts-type-forge';
1
+ import { type Intersection, type NonEmptyTuple } from 'ts-type-forge';
2
2
  import { type AnyType, type Type, type TypeOf } from '../type.mjs';
3
- export declare const intersection: <const Types extends NonEmptyArray<AnyType>>(types: Types, defaultType: IntersectionType<Types>, options?: Partial<Readonly<{
3
+ export declare const intersection: <const Types extends NonEmptyTuple<AnyType>>(types: Types, defaultType: IntersectionType<Types>, options?: Partial<Readonly<{
4
4
  typeName: string;
5
5
  }>>) => IntersectionType<Types>;
6
- type IntersectionType<Types extends NonEmptyArray<AnyType>> = Type<IntersectionTypeValue<Types>>;
7
- type IntersectionTypeValue<Types extends NonEmptyArray<AnyType>> = TsFortressInternal.IntersectionTypeValueImpl<Types>;
6
+ type IntersectionType<Types extends NonEmptyTuple<AnyType>> = Type<IntersectionTypeValue<Types>>;
7
+ type IntersectionTypeValue<Types extends NonEmptyTuple<AnyType>> = TsFortressInternal.IntersectionTypeValueImpl<Types>;
8
8
  declare namespace TsFortressInternal {
9
- export type IntersectionTypeValueImpl<Types extends NonEmptyArray<AnyType>> = Intersection<Cast0<UnwrapTypeList<Types>>>;
10
- type Cast0<T> = readonly [T] extends readonly [NonEmptyArray<unknown>] ? T : never;
9
+ export type IntersectionTypeValueImpl<Types extends NonEmptyTuple<AnyType>> = Intersection<Cast0<UnwrapTypeList<Types>>>;
10
+ type Cast0<T> = readonly [T] extends readonly [NonEmptyTuple<unknown>] ? T : never;
11
11
  export {};
12
12
  }
13
13
  type UnwrapTypeList<Types extends readonly AnyType[]> = TsFortressInternal.UnwrapTypeImpl<Types>;