ts-fortress 8.0.0 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/array/array-at-least-length.d.mts +6 -2
- package/dist/array/array-at-least-length.d.mts.map +1 -1
- package/dist/array/array-at-least-length.mjs +6 -8
- package/dist/array/array-at-least-length.mjs.map +1 -1
- package/dist/array/array-at-most-length.d.mts +6 -2
- package/dist/array/array-at-most-length.d.mts.map +1 -1
- package/dist/array/array-at-most-length.mjs +4 -7
- package/dist/array/array-at-most-length.mjs.map +1 -1
- package/dist/array/array-bounded-length.d.mts +15 -3
- package/dist/array/array-bounded-length.d.mts.map +1 -1
- package/dist/array/array-bounded-length.mjs +7 -9
- package/dist/array/array-bounded-length.mjs.map +1 -1
- package/package.json +1 -1
- package/src/array/array-at-least-length.mts +35 -10
- package/src/array/array-at-least-length.test.mts +27 -0
- package/src/array/array-at-most-length.mts +33 -12
- package/src/array/array-at-most-length.test.mts +27 -0
- package/src/array/array-bounded-length.mts +72 -15
- package/src/array/array-bounded-length.test.mts +41 -1
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { type ArrayAtLeastLen, type SmallUint } from 'ts-type-forge';
|
|
2
2
|
import { type Type } from '../type.mjs';
|
|
3
3
|
export type { ArrayAtLeastLen } from 'ts-type-forge';
|
|
4
|
-
export declare
|
|
4
|
+
export declare function arrayAtLeastLength<A, N extends SmallUint>(size: N, elementType: Type<A>, options?: Partial<Readonly<{
|
|
5
5
|
typeName: string;
|
|
6
6
|
defaultValue: ArrayAtLeastLen<N, A>;
|
|
7
|
-
}>>)
|
|
7
|
+
}>>): Type<ArrayAtLeastLen<N, A>>;
|
|
8
|
+
export declare function arrayAtLeastLength<A>(size: number, elementType: Type<A>, options?: Partial<Readonly<{
|
|
9
|
+
typeName: string;
|
|
10
|
+
defaultValue: readonly A[];
|
|
11
|
+
}>>): Type<readonly A[]>;
|
|
8
12
|
//# sourceMappingURL=array-at-least-length.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array-at-least-length.d.mts","sourceRoot":"","sources":["../../src/array/array-at-least-length.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAUxC,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,
|
|
1
|
+
{"version":3,"file":"array-at-least-length.d.mts","sourceRoot":"","sources":["../../src/array/array-at-least-length.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAUxC,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,CAAC,SAAS,SAAS,EACvD,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,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CACrC,CAAC,CACH,GACA,IAAI,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAI/B,wBAAgB,kBAAkB,CAAC,CAAC,EAClC,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"}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { memoizeFunction, Arr, Result } from 'ts-data-forge';
|
|
1
|
+
import { memoizeFunction, Arr, asUint32, Result } from 'ts-data-forge';
|
|
2
2
|
import { createAssertFn } from '../utils/create-assert-fn.mjs';
|
|
3
3
|
import { createCastFn } from '../utils/create-cast-fn.mjs';
|
|
4
4
|
import { createIsFn } from '../utils/create-is-fn.mjs';
|
|
5
5
|
import { createPrimitiveValidationError, prependIndexToValidationErrors } from '../utils/validation-error.mjs';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
function arrayAtLeastLength(size, elementType, options) {
|
|
8
8
|
const typeName = options?.typeName ?? `ArrayAtLeastLen<${size}, ${elementType.typeName}>`;
|
|
9
9
|
const getDefaultValue = memoizeFunction(() => options?.defaultValue ??
|
|
10
|
-
//
|
|
11
|
-
Arr.create(size, elementType.defaultValue));
|
|
10
|
+
// An array of `size` elements is the shortest value satisfying the bound.
|
|
11
|
+
Arr.create(asUint32(size), elementType.defaultValue));
|
|
12
12
|
const validate = (a) => {
|
|
13
13
|
if (!Arr.isArray(a)) {
|
|
14
14
|
return Result.err([
|
|
@@ -50,9 +50,7 @@ const arrayAtLeastLength = (size, elementType, options) => {
|
|
|
50
50
|
return Result.ok(a);
|
|
51
51
|
};
|
|
52
52
|
const fill = (a) => Arr.isArray(a)
|
|
53
|
-
?
|
|
54
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
55
|
-
Arr.map(Arr.seq(size), (i) => elementType.fill(a[i]))
|
|
53
|
+
? Arr.map(Arr.seq(asUint32(size)), (i) => elementType.fill(a[i]))
|
|
56
54
|
: getDefaultValue();
|
|
57
55
|
return {
|
|
58
56
|
typeName,
|
|
@@ -65,7 +63,7 @@ const arrayAtLeastLength = (size, elementType, options) => {
|
|
|
65
63
|
cast: createCastFn(validate),
|
|
66
64
|
assertIs: createAssertFn(validate),
|
|
67
65
|
};
|
|
68
|
-
}
|
|
66
|
+
}
|
|
69
67
|
|
|
70
68
|
export { arrayAtLeastLength };
|
|
71
69
|
//# sourceMappingURL=array-at-least-length.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array-at-least-length.mjs","sources":["../../src/array/array-at-least-length.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"array-at-least-length.mjs","sources":["../../src/array/array-at-least-length.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;SAsCgB,kBAAkB,CAChC,IAAY,EACZ,WAAoB,EACpB,OAKC,EAAA;AAID,IAAA,MAAM,QAAQ,GACZ,OAAO,EAAE,QAAQ,IAAI,CAAA,gBAAA,EAAmB,IAAI,CAAA,EAAA,EAAK,WAAW,CAAC,QAAQ,GAAG;IAE1E,MAAM,eAAe,GAAG,eAAe,CACrC,MACE,OAAO,EAAE,YAAY;;AAErB,QAAA,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,YAAY,CAAC,CACvD;AAED,IAAA,MAAM,QAAQ,GAAwB,CAAC,CAAC,KAAI;QAC1C,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YACnB,OAAO,MAAM,CAAC,GAAG,CAAC;AAChB,gBAAA,8BAA8B,CAAC;AAC7B,oBAAA,WAAW,EAAE,CAAC;AACd,oBAAA,YAAY,EAAE,OAAO;oBACrB,QAAQ;AACR,oBAAA,OAAO,EAAE,SAAS;iBACnB,CAAC;AACH,aAAA,CAAC;QACJ;AAEA,QAAA,IAAI,CAAC,CAAC,MAAM,GAAG,IAAI,EAAE;YACnB,OAAO,MAAM,CAAC,GAAG,CAAC;AAChB,gBAAA;AACE,oBAAA,IAAI,EAAE,EAAE;AACR,oBAAA,WAAW,EAAE,CAAC;AACd,oBAAA,YAAY,EAAE,QAAQ;oBACtB,QAAQ;AACR,oBAAA,OAAO,EAAE;AACP,wBAAA,IAAI,EAAE,kBAAkB;AACxB,wBAAA,SAAS,EAAE,IAAI;wBACf,YAAY,EAAE,CAAC,CAAC,MAAM;AACvB,qBAAA;AACwB,iBAAA;AAC5B,aAAA,CAAC;QACJ;AAEA,QAAA,MAAM,MAAM,GAA+B,GAAG,CAAC,QAAQ,CAAC,aAAS;AAC/D,YAAA,KAAK,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;gBACrC,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;AAEpC,gBAAA,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;oBACrB,OAAO,8BAA8B,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC;gBACzD;YACF;AACF,QAAA,CAAC,CAAC;AAEF,QAAA,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;AAC1B,YAAA,OAAO,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;QAC3B;;AAGA,QAAA,OAAO,MAAM,CAAC,EAAE,CAAC,CAAiB,CAAC;AACrC,IAAA,CAAC;AAED,IAAA,MAAM,IAAI,GAAoB,CAAC,CAAC,KAC9B,GAAG,CAAC,OAAO,CAAC,CAAC;AACX,UAAE,GAAG,CAAC,GAAG,CACL,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EACvB,CAAC,CAAC,KAAK,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAa;UAE3C,eAAe,EAAE;IAEvB,OAAO;QACL,QAAQ;AACR,QAAA,IAAI,YAAY,GAAA;YACd,OAAO,eAAe,EAAE;QAC1B,CAAC;QACD,IAAI;QACJ,QAAQ;AACR,QAAA,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC;AACxB,QAAA,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC;AAC5B,QAAA,QAAQ,EAAE,cAAc,CAAC,QAAQ,CAAC;KACnC;AACH;;;;"}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import { type ArrayAtMostLen, type SmallUint } from 'ts-type-forge';
|
|
2
2
|
import { type Type } from '../type.mjs';
|
|
3
3
|
export type { ArrayAtMostLen } from 'ts-type-forge';
|
|
4
|
-
export declare
|
|
4
|
+
export declare function arrayAtMostLength<A, N extends SmallUint>(size: N, elementType: Type<A>, options?: Partial<Readonly<{
|
|
5
5
|
typeName: string;
|
|
6
6
|
defaultValue: ArrayAtMostLen<N, A>;
|
|
7
|
-
}>>)
|
|
7
|
+
}>>): Type<ArrayAtMostLen<N, A>>;
|
|
8
|
+
export declare function arrayAtMostLength<A>(size: number, elementType: Type<A>, options?: Partial<Readonly<{
|
|
9
|
+
typeName: string;
|
|
10
|
+
defaultValue: readonly A[];
|
|
11
|
+
}>>): Type<readonly A[]>;
|
|
8
12
|
//# sourceMappingURL=array-at-most-length.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array-at-most-length.d.mts","sourceRoot":"","sources":["../../src/array/array-at-most-length.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAUxC,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,
|
|
1
|
+
{"version":3,"file":"array-at-most-length.d.mts","sourceRoot":"","sources":["../../src/array/array-at-most-length.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAUxC,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,CAAC,SAAS,SAAS,EACtD,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,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CACpC,CAAC,CACH,GACA,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAI9B,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,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"}
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { memoizeFunction, Arr, Result } from 'ts-data-forge';
|
|
1
|
+
import { memoizeFunction, Arr, Result, asUint32 } from 'ts-data-forge';
|
|
2
2
|
import { createAssertFn } from '../utils/create-assert-fn.mjs';
|
|
3
3
|
import { createCastFn } from '../utils/create-cast-fn.mjs';
|
|
4
4
|
import { createIsFn } from '../utils/create-is-fn.mjs';
|
|
5
5
|
import { createPrimitiveValidationError, prependIndexToValidationErrors } from '../utils/validation-error.mjs';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
function arrayAtMostLength(size, elementType, options) {
|
|
8
8
|
const typeName = options?.typeName ?? `ArrayAtMostLen<${size}, ${elementType.typeName}>`;
|
|
9
9
|
const getDefaultValue = memoizeFunction(() => options?.defaultValue ??
|
|
10
10
|
// The empty array is the shortest value satisfying `length <= size`.
|
|
11
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
12
11
|
Arr.create(0, elementType.defaultValue));
|
|
13
12
|
const validate = (a) => {
|
|
14
13
|
if (!Arr.isArray(a)) {
|
|
@@ -52,9 +51,7 @@ const arrayAtMostLength = (size, elementType, options) => {
|
|
|
52
51
|
};
|
|
53
52
|
const fill = (a) => Arr.isArray(a)
|
|
54
53
|
? // Keep the input but trim down to at most `size` elements.
|
|
55
|
-
|
|
56
|
-
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
57
|
-
Arr.map(Arr.take(a, size), (el) => elementType.fill(el))
|
|
54
|
+
Arr.map(Arr.take(a, asUint32(size)), (el) => elementType.fill(el))
|
|
58
55
|
: getDefaultValue();
|
|
59
56
|
return {
|
|
60
57
|
typeName,
|
|
@@ -67,7 +64,7 @@ const arrayAtMostLength = (size, elementType, options) => {
|
|
|
67
64
|
cast: createCastFn(validate),
|
|
68
65
|
assertIs: createAssertFn(validate),
|
|
69
66
|
};
|
|
70
|
-
}
|
|
67
|
+
}
|
|
71
68
|
|
|
72
69
|
export { arrayAtMostLength };
|
|
73
70
|
//# sourceMappingURL=array-at-most-length.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array-at-most-length.mjs","sources":["../../src/array/array-at-most-length.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"array-at-most-length.mjs","sources":["../../src/array/array-at-most-length.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;SAsCgB,iBAAiB,CAC/B,IAAY,EACZ,WAAoB,EACpB,OAKC,EAAA;AAID,IAAA,MAAM,QAAQ,GACZ,OAAO,EAAE,QAAQ,IAAI,CAAA,eAAA,EAAkB,IAAI,CAAA,EAAA,EAAK,WAAW,CAAC,QAAQ,GAAG;IAEzE,MAAM,eAAe,GAAG,eAAe,CACrC,MACE,OAAO,EAAE,YAAY;;QAErB,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,WAAW,CAAC,YAAY,CAAC,CAC1C;AAED,IAAA,MAAM,QAAQ,GAAwB,CAAC,CAAC,KAAI;QAC1C,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YACnB,OAAO,MAAM,CAAC,GAAG,CAAC;AAChB,gBAAA,8BAA8B,CAAC;AAC7B,oBAAA,WAAW,EAAE,CAAC;AACd,oBAAA,YAAY,EAAE,OAAO;oBACrB,QAAQ;AACR,oBAAA,OAAO,EAAE,SAAS;iBACnB,CAAC;AACH,aAAA,CAAC;QACJ;AAEA,QAAA,IAAI,CAAC,CAAC,MAAM,GAAG,IAAI,EAAE;YACnB,OAAO,MAAM,CAAC,GAAG,CAAC;AAChB,gBAAA;AACE,oBAAA,IAAI,EAAE,EAAE;AACR,oBAAA,WAAW,EAAE,CAAC;AACd,oBAAA,YAAY,EAAE,QAAQ;oBACtB,QAAQ;AACR,oBAAA,OAAO,EAAE;AACP,wBAAA,IAAI,EAAE,kBAAkB;AACxB,wBAAA,SAAS,EAAE,IAAI;wBACf,YAAY,EAAE,CAAC,CAAC,MAAM;AACvB,qBAAA;AACwB,iBAAA;AAC5B,aAAA,CAAC;QACJ;AAEA,QAAA,MAAM,MAAM,GAA+B,GAAG,CAAC,QAAQ,CAAC,aAAS;AAC/D,YAAA,KAAK,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;gBACrC,MAAM,GAAG,GAAG,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;AAEpC,gBAAA,IAAI,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;oBACrB,OAAO,8BAA8B,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC;gBACzD;YACF;AACF,QAAA,CAAC,CAAC;AAEF,QAAA,IAAI,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;AAC1B,YAAA,OAAO,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;QAC3B;;AAGA,QAAA,OAAO,MAAM,CAAC,EAAE,CAAC,CAAiB,CAAC;AACrC,IAAA,CAAC;AAED,IAAA,MAAM,IAAI,GAAoB,CAAC,CAAC,KAC9B,GAAG,CAAC,OAAO,CAAC,CAAC;AACX;YACE,GAAG,CAAC,GAAG,CACL,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,EAC3B,CAAC,EAAE,KAAK,WAAW,CAAC,IAAI,CAAC,EAAE,CAAa;UAE1C,eAAe,EAAE;IAEvB,OAAO;QACL,QAAQ;AACR,QAAA,IAAI,YAAY,GAAA;YACd,OAAO,eAAe,EAAE;QAC1B,CAAC;QACD,IAAI;QACJ,QAAQ;AACR,QAAA,EAAE,EAAE,UAAU,CAAC,QAAQ,CAAC;AACxB,QAAA,IAAI,EAAE,YAAY,CAAC,QAAQ,CAAC;AAC5B,QAAA,QAAQ,EAAE,cAAc,CAAC,QAAQ,CAAC;KACnC;AACH;;;;"}
|
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
import { type ArrayBoundedLen, type SmallUint } from 'ts-type-forge';
|
|
1
|
+
import { type ArrayAtLeastLen, type ArrayAtMostLen, type ArrayBoundedLen, type SmallUint } from 'ts-type-forge';
|
|
2
2
|
import { type Type } from '../type.mjs';
|
|
3
3
|
export type { ArrayBoundedLen } from 'ts-type-forge';
|
|
4
|
-
export declare
|
|
4
|
+
export declare function arrayBoundedLength<A, Min extends SmallUint, Max extends SmallUint>(min: Min, max: Max, elementType: Type<A>, options?: Partial<Readonly<{
|
|
5
5
|
typeName: string;
|
|
6
6
|
defaultValue: ArrayBoundedLen<Min, Max, A>;
|
|
7
|
-
}>>)
|
|
7
|
+
}>>): Type<ArrayBoundedLen<Min, Max, A>>;
|
|
8
|
+
export declare function arrayBoundedLength<A, Min extends SmallUint>(min: Min, max: number, elementType: Type<A>, options?: Partial<Readonly<{
|
|
9
|
+
typeName: string;
|
|
10
|
+
defaultValue: ArrayAtLeastLen<Min, A>;
|
|
11
|
+
}>>): Type<ArrayAtLeastLen<Min, A>>;
|
|
12
|
+
export declare function arrayBoundedLength<A, Max extends SmallUint>(min: number, max: Max, elementType: Type<A>, options?: Partial<Readonly<{
|
|
13
|
+
typeName: string;
|
|
14
|
+
defaultValue: ArrayAtMostLen<Max, A>;
|
|
15
|
+
}>>): Type<ArrayAtMostLen<Max, A>>;
|
|
16
|
+
export declare function arrayBoundedLength<A>(min: number, max: number, elementType: Type<A>, options?: Partial<Readonly<{
|
|
17
|
+
typeName: string;
|
|
18
|
+
defaultValue: readonly A[];
|
|
19
|
+
}>>): Type<readonly A[]>;
|
|
8
20
|
//# sourceMappingURL=array-bounded-length.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array-bounded-length.d.mts","sourceRoot":"","sources":["../../src/array/array-bounded-length.mts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"array-bounded-length.d.mts","sourceRoot":"","sources":["../../src/array/array-bounded-length.mts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,SAAS,EACf,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAUxC,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,wBAAgB,kBAAkB,CAChC,CAAC,EACD,GAAG,SAAS,SAAS,EACrB,GAAG,SAAS,SAAS,EAErB,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,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;CAC5C,CAAC,CACH,GACA,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AAItC,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,GAAG,SAAS,SAAS,EACzD,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,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;CACvC,CAAC,CACH,GACA,IAAI,CAAC,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;AAIjC,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,GAAG,SAAS,SAAS,EACzD,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"}
|
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import { memoizeFunction, Arr, Result } from 'ts-data-forge';
|
|
1
|
+
import { memoizeFunction, Arr, asUint32, Result } from 'ts-data-forge';
|
|
2
2
|
import { createAssertFn } from '../utils/create-assert-fn.mjs';
|
|
3
3
|
import { createCastFn } from '../utils/create-cast-fn.mjs';
|
|
4
4
|
import { createIsFn } from '../utils/create-is-fn.mjs';
|
|
5
5
|
import { createPrimitiveValidationError, prependIndexToValidationErrors } from '../utils/validation-error.mjs';
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
function arrayBoundedLength(min, max, elementType, options) {
|
|
8
8
|
const typeName = options?.typeName ??
|
|
9
9
|
`ArrayBoundedLen<${min}, ${max}, ${elementType.typeName}>`;
|
|
10
10
|
const getDefaultValue = memoizeFunction(() => options?.defaultValue ??
|
|
11
11
|
// An array of the minimum length is the shortest value within the range.
|
|
12
|
-
|
|
13
|
-
Arr.create(min, elementType.defaultValue));
|
|
12
|
+
Arr.create(asUint32(min), elementType.defaultValue));
|
|
14
13
|
const validate = (a) => {
|
|
15
14
|
if (!Arr.isArray(a)) {
|
|
16
15
|
return Result.err([
|
|
@@ -57,11 +56,10 @@ const arrayBoundedLength = (min, max, elementType, options) => {
|
|
|
57
56
|
return getDefaultValue();
|
|
58
57
|
}
|
|
59
58
|
// Trim down to at most `max`, then pad up to at least `min`.
|
|
60
|
-
const capped = Arr.take(a, max);
|
|
61
|
-
|
|
62
|
-
return (capped.length >= min
|
|
59
|
+
const capped = Arr.take(a, asUint32(max));
|
|
60
|
+
return capped.length >= min
|
|
63
61
|
? Arr.map(capped, (el) => elementType.fill(el))
|
|
64
|
-
: Arr.map(Arr.seq(min), (i) => elementType.fill(capped[i]))
|
|
62
|
+
: Arr.map(Arr.seq(asUint32(min)), (i) => elementType.fill(capped[i]));
|
|
65
63
|
};
|
|
66
64
|
return {
|
|
67
65
|
typeName,
|
|
@@ -74,7 +72,7 @@ const arrayBoundedLength = (min, max, elementType, options) => {
|
|
|
74
72
|
cast: createCastFn(validate),
|
|
75
73
|
assertIs: createAssertFn(validate),
|
|
76
74
|
};
|
|
77
|
-
}
|
|
75
|
+
}
|
|
78
76
|
|
|
79
77
|
export { arrayBoundedLength };
|
|
80
78
|
//# sourceMappingURL=array-bounded-length.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array-bounded-length.mjs","sources":["../../src/array/array-bounded-length.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"array-bounded-length.mjs","sources":["../../src/array/array-bounded-length.mts"],"sourcesContent":[null],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Arr, memoizeFunction, Result } from 'ts-data-forge';
|
|
1
|
+
import { Arr, asUint32, memoizeFunction, Result } from 'ts-data-forge';
|
|
2
2
|
import { type ArrayAtLeastLen, type SmallUint } from 'ts-type-forge';
|
|
3
3
|
import { type Type } from '../type.mjs';
|
|
4
4
|
import {
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
|
|
13
13
|
export type { ArrayAtLeastLen } from 'ts-type-forge';
|
|
14
14
|
|
|
15
|
-
export
|
|
15
|
+
export function arrayAtLeastLength<A, N extends SmallUint>(
|
|
16
16
|
size: N,
|
|
17
17
|
elementType: Type<A>,
|
|
18
18
|
options?: Partial<
|
|
@@ -21,8 +21,32 @@ export const arrayAtLeastLength = <A, N extends SmallUint>(
|
|
|
21
21
|
defaultValue: ArrayAtLeastLen<N, A>;
|
|
22
22
|
}>
|
|
23
23
|
>,
|
|
24
|
-
): Type<ArrayAtLeastLen<N, A
|
|
25
|
-
|
|
24
|
+
): Type<ArrayAtLeastLen<N, A>>;
|
|
25
|
+
|
|
26
|
+
// For sizes outside `SmallUint` the exact length cannot be encoded in the type,
|
|
27
|
+
// so the result length is left unconstrained (`readonly A[]`).
|
|
28
|
+
export function arrayAtLeastLength<A>(
|
|
29
|
+
size: number,
|
|
30
|
+
elementType: Type<A>,
|
|
31
|
+
options?: Partial<
|
|
32
|
+
Readonly<{
|
|
33
|
+
typeName: string;
|
|
34
|
+
defaultValue: readonly A[];
|
|
35
|
+
}>
|
|
36
|
+
>,
|
|
37
|
+
): Type<readonly A[]>;
|
|
38
|
+
|
|
39
|
+
export function arrayAtLeastLength<A>(
|
|
40
|
+
size: number,
|
|
41
|
+
elementType: Type<A>,
|
|
42
|
+
options?: Partial<
|
|
43
|
+
Readonly<{
|
|
44
|
+
typeName: string;
|
|
45
|
+
defaultValue: readonly A[];
|
|
46
|
+
}>
|
|
47
|
+
>,
|
|
48
|
+
): Type<readonly A[]> {
|
|
49
|
+
type T = readonly A[];
|
|
26
50
|
|
|
27
51
|
const typeName =
|
|
28
52
|
options?.typeName ?? `ArrayAtLeastLen<${size}, ${elementType.typeName}>`;
|
|
@@ -30,8 +54,8 @@ export const arrayAtLeastLength = <A, N extends SmallUint>(
|
|
|
30
54
|
const getDefaultValue = memoizeFunction(
|
|
31
55
|
(): T =>
|
|
32
56
|
options?.defaultValue ??
|
|
33
|
-
//
|
|
34
|
-
|
|
57
|
+
// An array of `size` elements is the shortest value satisfying the bound.
|
|
58
|
+
Arr.create(asUint32(size), elementType.defaultValue),
|
|
35
59
|
);
|
|
36
60
|
|
|
37
61
|
const validate: Type<T>['validate'] = (a) => {
|
|
@@ -82,9 +106,10 @@ export const arrayAtLeastLength = <A, N extends SmallUint>(
|
|
|
82
106
|
|
|
83
107
|
const fill: Type<T>['fill'] = (a) =>
|
|
84
108
|
Arr.isArray(a)
|
|
85
|
-
?
|
|
86
|
-
|
|
87
|
-
|
|
109
|
+
? Arr.map(
|
|
110
|
+
Arr.seq(asUint32(size)),
|
|
111
|
+
(i) => elementType.fill(a[i]) satisfies A,
|
|
112
|
+
)
|
|
88
113
|
: getDefaultValue();
|
|
89
114
|
|
|
90
115
|
return {
|
|
@@ -98,4 +123,4 @@ export const arrayAtLeastLength = <A, N extends SmallUint>(
|
|
|
98
123
|
cast: createCastFn(validate),
|
|
99
124
|
assertIs: createAssertFn(validate),
|
|
100
125
|
};
|
|
101
|
-
}
|
|
126
|
+
}
|
|
@@ -219,4 +219,31 @@ describe(arrayAtLeastLength, () => {
|
|
|
219
219
|
assert.deepStrictEqual(xs.fill(ys), [1, 2, 3]);
|
|
220
220
|
});
|
|
221
221
|
});
|
|
222
|
+
|
|
223
|
+
describe('size outside SmallUint', () => {
|
|
224
|
+
// A literal beyond `SmallUint`'s range selects the fallback overload, whose
|
|
225
|
+
// result length is unconstrained.
|
|
226
|
+
const big = arrayAtLeastLength(100, number());
|
|
227
|
+
|
|
228
|
+
expectType<TypeOf<typeof big>, readonly number[]>('=');
|
|
229
|
+
|
|
230
|
+
expectType<typeof big.defaultValue, readonly number[]>('=');
|
|
231
|
+
|
|
232
|
+
// A plain `number` (not a literal) also selects the fallback overload.
|
|
233
|
+
const dynamicSize: number = 5;
|
|
234
|
+
|
|
235
|
+
const dyn = arrayAtLeastLength(dynamicSize, number());
|
|
236
|
+
|
|
237
|
+
expectType<TypeOf<typeof dyn>, readonly number[]>('=');
|
|
238
|
+
|
|
239
|
+
test('default value has the requested length', () => {
|
|
240
|
+
expect(big.defaultValue).toHaveLength(100);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test('validates the minimum length at runtime', () => {
|
|
244
|
+
assert.isTrue(dyn.is([0, 0, 0, 0, 0]));
|
|
245
|
+
|
|
246
|
+
assert.isFalse(dyn.is([0, 0, 0, 0]));
|
|
247
|
+
});
|
|
248
|
+
});
|
|
222
249
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Arr, memoizeFunction, Result } from 'ts-data-forge';
|
|
1
|
+
import { Arr, asUint32, memoizeFunction, Result } from 'ts-data-forge';
|
|
2
2
|
import { type ArrayAtMostLen, type SmallUint } from 'ts-type-forge';
|
|
3
3
|
import { type Type } from '../type.mjs';
|
|
4
4
|
import {
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
|
|
13
13
|
export type { ArrayAtMostLen } from 'ts-type-forge';
|
|
14
14
|
|
|
15
|
-
export
|
|
15
|
+
export function arrayAtMostLength<A, N extends SmallUint>(
|
|
16
16
|
size: N,
|
|
17
17
|
elementType: Type<A>,
|
|
18
18
|
options?: Partial<
|
|
@@ -21,8 +21,32 @@ export const arrayAtMostLength = <A, N extends SmallUint>(
|
|
|
21
21
|
defaultValue: ArrayAtMostLen<N, A>;
|
|
22
22
|
}>
|
|
23
23
|
>,
|
|
24
|
-
): Type<ArrayAtMostLen<N, A
|
|
25
|
-
|
|
24
|
+
): Type<ArrayAtMostLen<N, A>>;
|
|
25
|
+
|
|
26
|
+
// For sizes outside `SmallUint` the exact length cannot be encoded in the type,
|
|
27
|
+
// so the result length is left unconstrained (`readonly A[]`).
|
|
28
|
+
export function arrayAtMostLength<A>(
|
|
29
|
+
size: number,
|
|
30
|
+
elementType: Type<A>,
|
|
31
|
+
options?: Partial<
|
|
32
|
+
Readonly<{
|
|
33
|
+
typeName: string;
|
|
34
|
+
defaultValue: readonly A[];
|
|
35
|
+
}>
|
|
36
|
+
>,
|
|
37
|
+
): Type<readonly A[]>;
|
|
38
|
+
|
|
39
|
+
export function arrayAtMostLength<A>(
|
|
40
|
+
size: number,
|
|
41
|
+
elementType: Type<A>,
|
|
42
|
+
options?: Partial<
|
|
43
|
+
Readonly<{
|
|
44
|
+
typeName: string;
|
|
45
|
+
defaultValue: readonly A[];
|
|
46
|
+
}>
|
|
47
|
+
>,
|
|
48
|
+
): Type<readonly A[]> {
|
|
49
|
+
type T = readonly A[];
|
|
26
50
|
|
|
27
51
|
const typeName =
|
|
28
52
|
options?.typeName ?? `ArrayAtMostLen<${size}, ${elementType.typeName}>`;
|
|
@@ -31,8 +55,7 @@ export const arrayAtMostLength = <A, N extends SmallUint>(
|
|
|
31
55
|
(): T =>
|
|
32
56
|
options?.defaultValue ??
|
|
33
57
|
// The empty array is the shortest value satisfying `length <= size`.
|
|
34
|
-
|
|
35
|
-
(Arr.create(0, elementType.defaultValue) as T),
|
|
58
|
+
Arr.create(0, elementType.defaultValue),
|
|
36
59
|
);
|
|
37
60
|
|
|
38
61
|
const validate: Type<T>['validate'] = (a) => {
|
|
@@ -84,12 +107,10 @@ export const arrayAtMostLength = <A, N extends SmallUint>(
|
|
|
84
107
|
const fill: Type<T>['fill'] = (a) =>
|
|
85
108
|
Arr.isArray(a)
|
|
86
109
|
? // Keep the input but trim down to at most `size` elements.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
(Arr.map(
|
|
90
|
-
Arr.take(a, size),
|
|
110
|
+
Arr.map(
|
|
111
|
+
Arr.take(a, asUint32(size)),
|
|
91
112
|
(el) => elementType.fill(el) satisfies A,
|
|
92
|
-
)
|
|
113
|
+
)
|
|
93
114
|
: getDefaultValue();
|
|
94
115
|
|
|
95
116
|
return {
|
|
@@ -103,4 +124,4 @@ export const arrayAtMostLength = <A, N extends SmallUint>(
|
|
|
103
124
|
cast: createCastFn(validate),
|
|
104
125
|
assertIs: createAssertFn(validate),
|
|
105
126
|
};
|
|
106
|
-
}
|
|
127
|
+
}
|
|
@@ -203,4 +203,31 @@ describe(arrayAtMostLength, () => {
|
|
|
203
203
|
assert.deepStrictEqual(xs.fill(ys), [1, 2, 3]);
|
|
204
204
|
});
|
|
205
205
|
});
|
|
206
|
+
|
|
207
|
+
describe('size outside SmallUint', () => {
|
|
208
|
+
// A literal beyond `SmallUint`'s range selects the fallback overload, whose
|
|
209
|
+
// result length is unconstrained.
|
|
210
|
+
const big = arrayAtMostLength(100, number());
|
|
211
|
+
|
|
212
|
+
expectType<TypeOf<typeof big>, readonly number[]>('=');
|
|
213
|
+
|
|
214
|
+
expectType<typeof big.defaultValue, readonly number[]>('=');
|
|
215
|
+
|
|
216
|
+
// A plain `number` (not a literal) also selects the fallback overload.
|
|
217
|
+
const dynamicSize: number = 2;
|
|
218
|
+
|
|
219
|
+
const dyn = arrayAtMostLength(dynamicSize, number());
|
|
220
|
+
|
|
221
|
+
expectType<TypeOf<typeof dyn>, readonly number[]>('=');
|
|
222
|
+
|
|
223
|
+
test('default value is the empty array', () => {
|
|
224
|
+
assert.deepStrictEqual(big.defaultValue, []);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
test('validates the maximum length at runtime', () => {
|
|
228
|
+
assert.isTrue(dyn.is([0, 0]));
|
|
229
|
+
|
|
230
|
+
assert.isFalse(dyn.is([0, 0, 0]));
|
|
231
|
+
});
|
|
232
|
+
});
|
|
206
233
|
});
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import { Arr, memoizeFunction, Result } from 'ts-data-forge';
|
|
2
|
-
import {
|
|
1
|
+
import { Arr, asUint32, memoizeFunction, Result } from 'ts-data-forge';
|
|
2
|
+
import {
|
|
3
|
+
type ArrayAtLeastLen,
|
|
4
|
+
type ArrayAtMostLen,
|
|
5
|
+
type ArrayBoundedLen,
|
|
6
|
+
type SmallUint,
|
|
7
|
+
} from 'ts-type-forge';
|
|
3
8
|
import { type Type } from '../type.mjs';
|
|
4
9
|
import {
|
|
5
10
|
createAssertFn,
|
|
@@ -12,7 +17,7 @@ import {
|
|
|
12
17
|
|
|
13
18
|
export type { ArrayBoundedLen } from 'ts-type-forge';
|
|
14
19
|
|
|
15
|
-
export
|
|
20
|
+
export function arrayBoundedLength<
|
|
16
21
|
A,
|
|
17
22
|
Min extends SmallUint,
|
|
18
23
|
Max extends SmallUint,
|
|
@@ -26,8 +31,61 @@ export const arrayBoundedLength = <
|
|
|
26
31
|
defaultValue: ArrayBoundedLen<Min, Max, A>;
|
|
27
32
|
}>
|
|
28
33
|
>,
|
|
29
|
-
): Type<ArrayBoundedLen<Min, Max, A
|
|
30
|
-
|
|
34
|
+
): Type<ArrayBoundedLen<Min, Max, A>>;
|
|
35
|
+
|
|
36
|
+
// Only the lower bound is in `SmallUint`, so the upper bound is dropped from the
|
|
37
|
+
// result type and only the "at least `min`" guarantee is kept.
|
|
38
|
+
export function arrayBoundedLength<A, Min extends SmallUint>(
|
|
39
|
+
min: Min,
|
|
40
|
+
max: number,
|
|
41
|
+
elementType: Type<A>,
|
|
42
|
+
options?: Partial<
|
|
43
|
+
Readonly<{
|
|
44
|
+
typeName: string;
|
|
45
|
+
defaultValue: ArrayAtLeastLen<Min, A>;
|
|
46
|
+
}>
|
|
47
|
+
>,
|
|
48
|
+
): Type<ArrayAtLeastLen<Min, A>>;
|
|
49
|
+
|
|
50
|
+
// Only the upper bound is in `SmallUint`, so the lower bound is dropped from the
|
|
51
|
+
// result type and only the "at most `max`" guarantee is kept.
|
|
52
|
+
export function arrayBoundedLength<A, Max extends SmallUint>(
|
|
53
|
+
min: number,
|
|
54
|
+
max: Max,
|
|
55
|
+
elementType: Type<A>,
|
|
56
|
+
options?: Partial<
|
|
57
|
+
Readonly<{
|
|
58
|
+
typeName: string;
|
|
59
|
+
defaultValue: ArrayAtMostLen<Max, A>;
|
|
60
|
+
}>
|
|
61
|
+
>,
|
|
62
|
+
): Type<ArrayAtMostLen<Max, A>>;
|
|
63
|
+
|
|
64
|
+
// Neither bound is in `SmallUint`, so the result length is left unconstrained.
|
|
65
|
+
export function arrayBoundedLength<A>(
|
|
66
|
+
min: number,
|
|
67
|
+
max: number,
|
|
68
|
+
elementType: Type<A>,
|
|
69
|
+
options?: Partial<
|
|
70
|
+
Readonly<{
|
|
71
|
+
typeName: string;
|
|
72
|
+
defaultValue: readonly A[];
|
|
73
|
+
}>
|
|
74
|
+
>,
|
|
75
|
+
): Type<readonly A[]>;
|
|
76
|
+
|
|
77
|
+
export function arrayBoundedLength<A>(
|
|
78
|
+
min: number,
|
|
79
|
+
max: number,
|
|
80
|
+
elementType: Type<A>,
|
|
81
|
+
options?: Partial<
|
|
82
|
+
Readonly<{
|
|
83
|
+
typeName: string;
|
|
84
|
+
defaultValue: readonly A[];
|
|
85
|
+
}>
|
|
86
|
+
>,
|
|
87
|
+
): Type<readonly A[]> {
|
|
88
|
+
type T = readonly A[];
|
|
31
89
|
|
|
32
90
|
const typeName =
|
|
33
91
|
options?.typeName ??
|
|
@@ -37,8 +95,7 @@ export const arrayBoundedLength = <
|
|
|
37
95
|
(): T =>
|
|
38
96
|
options?.defaultValue ??
|
|
39
97
|
// An array of the minimum length is the shortest value within the range.
|
|
40
|
-
|
|
41
|
-
(Arr.create(min, elementType.defaultValue) as T),
|
|
98
|
+
Arr.create(asUint32(min), elementType.defaultValue),
|
|
42
99
|
);
|
|
43
100
|
|
|
44
101
|
const validate: Type<T>['validate'] = (a) => {
|
|
@@ -94,14 +151,14 @@ export const arrayBoundedLength = <
|
|
|
94
151
|
}
|
|
95
152
|
|
|
96
153
|
// Trim down to at most `max`, then pad up to at least `min`.
|
|
97
|
-
const capped = Arr.take(a, max);
|
|
154
|
+
const capped = Arr.take(a, asUint32(max));
|
|
98
155
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
156
|
+
return capped.length >= min
|
|
157
|
+
? Arr.map(capped, (el) => elementType.fill(el) satisfies A)
|
|
158
|
+
: Arr.map(
|
|
159
|
+
Arr.seq(asUint32(min)),
|
|
160
|
+
(i) => elementType.fill(capped[i]) satisfies A,
|
|
161
|
+
);
|
|
105
162
|
};
|
|
106
163
|
|
|
107
164
|
return {
|
|
@@ -115,4 +172,4 @@ export const arrayBoundedLength = <
|
|
|
115
172
|
cast: createCastFn(validate),
|
|
116
173
|
assertIs: createAssertFn(validate),
|
|
117
174
|
};
|
|
118
|
-
}
|
|
175
|
+
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import { expectType, Result } from 'ts-data-forge';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
type ArrayAtLeastLen,
|
|
4
|
+
type ArrayAtMostLen,
|
|
5
|
+
type ArrayBoundedLen,
|
|
6
|
+
} from 'ts-type-forge';
|
|
3
7
|
import { number } from '../primitives/index.mjs';
|
|
4
8
|
import { type TypeOf } from '../type.mjs';
|
|
5
9
|
import {
|
|
@@ -249,4 +253,40 @@ describe(arrayBoundedLength, () => {
|
|
|
249
253
|
assert.deepStrictEqual(xs.fill(ys), [1, 2, 3]);
|
|
250
254
|
});
|
|
251
255
|
});
|
|
256
|
+
|
|
257
|
+
describe('bounds outside SmallUint', () => {
|
|
258
|
+
// A plain `number` is outside `SmallUint`, so it drops the corresponding
|
|
259
|
+
// bound from the result type.
|
|
260
|
+
const dynamic: number = 3;
|
|
261
|
+
|
|
262
|
+
// min ∈ SmallUint & max ∉ SmallUint -> ArrayAtLeastLen<min, A>
|
|
263
|
+
const atLeast = arrayBoundedLength(2, dynamic, number());
|
|
264
|
+
|
|
265
|
+
expectType<TypeOf<typeof atLeast>, ArrayAtLeastLen<2, number>>('=');
|
|
266
|
+
|
|
267
|
+
// min ∉ SmallUint & max ∈ SmallUint -> ArrayAtMostLen<max, A>
|
|
268
|
+
const atMost = arrayBoundedLength(dynamic, 5, number());
|
|
269
|
+
|
|
270
|
+
expectType<TypeOf<typeof atMost>, ArrayAtMostLen<5, number>>('=');
|
|
271
|
+
|
|
272
|
+
// min ∉ SmallUint & max ∉ SmallUint -> readonly A[]
|
|
273
|
+
const unbounded = arrayBoundedLength(dynamic, dynamic, number());
|
|
274
|
+
|
|
275
|
+
expectType<TypeOf<typeof unbounded>, readonly number[]>('=');
|
|
276
|
+
|
|
277
|
+
test('still validates the range at runtime', () => {
|
|
278
|
+
// `atLeast` has range [2, 3], `atMost` has range [3, 5], `unbounded` [3, 3].
|
|
279
|
+
assert.isTrue(atLeast.is([0, 0]));
|
|
280
|
+
|
|
281
|
+
assert.isFalse(atLeast.is([0]));
|
|
282
|
+
|
|
283
|
+
assert.isTrue(atMost.is([0, 0, 0]));
|
|
284
|
+
|
|
285
|
+
assert.isFalse(atMost.is([0, 0]));
|
|
286
|
+
|
|
287
|
+
assert.isTrue(unbounded.is([0, 0, 0]));
|
|
288
|
+
|
|
289
|
+
assert.isFalse(unbounded.is([0, 0]));
|
|
290
|
+
});
|
|
291
|
+
});
|
|
252
292
|
});
|