ts-fortress 5.0.1 → 5.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/README.md CHANGED
@@ -910,6 +910,7 @@ type ValidationError = Readonly<{
910
910
  - `t.nonEmptyArray(elementType)` - Non-empty array validation
911
911
  - `t.tuple([t1, t2, ..., tN])` - Fixed-length tuple validation
912
912
  - `t.arrayOfLength(size, elementType)` - Fixed-length array validation
913
+ - `t.arrayAtLeastLength(size, elementType)` - Array validation with a minimum length
913
914
 
914
915
  ### Objects
915
916
 
@@ -0,0 +1,6 @@
1
+ import { type Type } from '../type.mjs';
2
+ export declare const arrayAtLeastLength: <A, N extends SmallUint>(size: N, elementType: Type<A>, options?: PartialReadonly<{
3
+ typeName: string;
4
+ defaultValue: ArrayAtLeastLen<N, A>;
5
+ }>) => Type<ArrayAtLeastLen<N, A>>;
6
+ //# sourceMappingURL=array-at-least-length.d.mts.map
@@ -0,0 +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,IAAI,EAAE,MAAM,aAAa,CAAC;AAWxC,eAAO,MAAM,kBAAkB,GAAI,CAAC,EAAE,CAAC,SAAS,SAAS,EACvD,MAAM,CAAC,EACP,aAAa,IAAI,CAAC,CAAC,CAAC,EACpB,UAAU,eAAe,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;CACrC,CAAC,KACD,IAAI,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAiE5B,CAAC"}
@@ -0,0 +1,63 @@
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 { createPrimitiveValidationError, prependIndexToValidationErrors } from '../utils/validation-error.mjs';
6
+
7
+ const arrayAtLeastLength = (size, elementType, options) => {
8
+ const { typeName = `ArrayAtLeastLen<${size}, ${elementType.typeName}>`,
9
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
10
+ defaultValue = Arr.create(size, elementType.defaultValue), } = options ?? {};
11
+ const validate = (a) => {
12
+ if (!Arr.isArray(a)) {
13
+ return Result.err([
14
+ createPrimitiveValidationError({
15
+ actualValue: a,
16
+ expectedType: 'array',
17
+ typeName,
18
+ }),
19
+ ]);
20
+ }
21
+ if (a.length < size) {
22
+ return Result.err([
23
+ {
24
+ path: [],
25
+ actualValue: a,
26
+ expectedType: typeName,
27
+ message: `Expected array of length ${size} or more, got length ${a.length}`,
28
+ typeName,
29
+ },
30
+ ]);
31
+ }
32
+ const errors = Arr.generate(function* () {
33
+ for (const [index, el] of a.entries()) {
34
+ const res = elementType.validate(el);
35
+ if (Result.isErr(res)) {
36
+ yield* prependIndexToValidationErrors(res.value, index);
37
+ }
38
+ }
39
+ });
40
+ if (errors.length > 0) {
41
+ return Result.err(errors);
42
+ }
43
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
44
+ return Result.ok(a);
45
+ };
46
+ const fill = (a) => Arr.isArray(a)
47
+ ? // TODO: remove as
48
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
49
+ Arr.map(Arr.seq(size), (i) => elementType.fill(a[i]))
50
+ : defaultValue;
51
+ return {
52
+ typeName,
53
+ defaultValue,
54
+ fill,
55
+ validate,
56
+ is: createIsFn(validate),
57
+ cast: createCastFn(validate),
58
+ assertIs: createAssertFn(validate),
59
+ };
60
+ };
61
+
62
+ export { arrayAtLeastLength };
63
+ //# sourceMappingURL=array-at-least-length.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array-at-least-length.mjs","sources":["../../src/array/array-at-least-length.mts"],"sourcesContent":[null],"names":[],"mappings":";;;;;;AAYO,MAAM,kBAAkB,GAAG,CAChC,IAAO,EACP,WAAoB,EACpB,OAGE,KAC6B;IAG/B,MAAM,EACJ,QAAQ,GAAG,CAAA,gBAAA,EAAmB,IAAI,CAAA,EAAA,EAAK,WAAW,CAAC,QAAQ,CAAA,CAAA,CAAG;;AAE9D,IAAA,YAAY,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,YAAY,CAAM,GAC/D,GAAG,OAAO,IAAI,EAAE;AAEjB,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;iBACT,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;AACtB,oBAAA,OAAO,EAAE,CAAA,yBAAA,EAA4B,IAAI,wBAAwB,CAAC,CAAC,MAAM,CAAA,CAAE;oBAC3E,QAAQ;AAC4B,iBAAA;AACvC,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;AACpC,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,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;AACrB,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;;YAEG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAa;UACjE,YAAY;IAElB,OAAO;QACL,QAAQ;QACR,YAAY;QACZ,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,3 +1,4 @@
1
+ export * from './array-at-least-length.mjs';
1
2
  export * from './array-of-length.mjs';
2
3
  export * from './array.mjs';
3
4
  export * from './non-empty-array.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/array/index.mts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../src/array/index.mts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,aAAa,CAAC"}
@@ -1,3 +1,4 @@
1
+ export { arrayAtLeastLength } from './array-at-least-length.mjs';
1
2
  export { arrayOfLength } from './array-of-length.mjs';
2
3
  export { array } from './array.mjs';
3
4
  export { nonEmptyArray } from './non-empty-array.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
1
+ {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -1,4 +1,5 @@
1
1
  export { FiniteNumber, Int, Int16, Int32, Int8, NonNegativeFiniteNumber, NonNegativeInt16, NonNegativeInt32, NonZeroFiniteNumber, NonZeroInt, NonZeroInt16, NonZeroInt32, NonZeroSafeInt, NonZeroUint16, NonZeroUint32, PositiveFiniteNumber, PositiveInt, PositiveInt16, PositiveInt32, PositiveSafeInt, PositiveUint16, PositiveUint32, Result, SafeInt, SafeUint, Uint, Uint16, Uint32, Uint8, asFiniteNumber, asInt, asInt16, asInt32, asInt8, asNonNegativeFiniteNumber, asNonNegativeInt16, asNonNegativeInt32, asNonZeroFiniteNumber, asNonZeroInt, asNonZeroInt16, asNonZeroInt32, asNonZeroSafeInt, asNonZeroUint16, asNonZeroUint32, asPositiveFiniteNumber, asPositiveInt, asPositiveInt16, asPositiveInt32, asPositiveSafeInt, asPositiveUint16, asPositiveUint32, asSafeInt, asSafeUint, asUint, asUint16, asUint32, asUint8, isBigint, isFiniteNumber, isInt, isInt16, isInt32, isInt8, isNonNegativeFiniteNumber, isNonNegativeInt16, isNonNegativeInt32, isNonZeroFiniteNumber, isNonZeroInt, isNonZeroInt16, isNonZeroInt32, isNonZeroSafeInt, isNonZeroUint16, isNonZeroUint32, isPositiveFiniteNumber, isPositiveInt, isPositiveInt16, isPositiveInt32, isPositiveSafeInt, isPositiveUint16, isPositiveUint32, isSafeInt, isSafeUint, isUint, isUint16, isUint32, isUint8 } from 'ts-data-forge';
2
+ export { arrayAtLeastLength } from './array/array-at-least-length.mjs';
2
3
  export { arrayOfLength } from './array/array-of-length.mjs';
3
4
  export { array } from './array/array.mjs';
4
5
  export { nonEmptyArray } from './array/non-empty-array.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"entry-point.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"entry-point.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/index.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ export { arrayAtLeastLength } from './array/array-at-least-length.mjs';
1
2
  export { arrayOfLength } from './array/array-of-length.mjs';
2
3
  export { array } from './array/array.mjs';
3
4
  export { nonEmptyArray } from './array/non-empty-array.mjs';
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.mjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-fortress",
3
- "version": "5.0.1",
3
+ "version": "5.1.0",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "typescript"
@@ -79,7 +79,7 @@
79
79
  "@semantic-release/github": "^11.0.6",
80
80
  "@semantic-release/npm": "^12.0.2",
81
81
  "@semantic-release/release-notes-generator": "^14.1.0",
82
- "@types/node": "^24.3.3",
82
+ "@types/node": "^24.5.2",
83
83
  "@vitest/coverage-v8": "^3.2.4",
84
84
  "@vitest/ui": "^3.2.4",
85
85
  "conventional-changelog-conventionalcommits": "^9.1.0",
@@ -94,9 +94,9 @@
94
94
  "prettier": "^3.6.2",
95
95
  "prettier-plugin-organize-imports": "^4.2.0",
96
96
  "prettier-plugin-packagejson": "^2.5.19",
97
- "rollup": "^4.50.1",
98
- "semantic-release": "^24.2.8",
99
- "ts-repo-utils": "^7.5.0",
97
+ "rollup": "^4.52.0",
98
+ "semantic-release": "^24.2.9",
99
+ "ts-repo-utils": "^7.7.0",
100
100
  "tslib": "^2.8.1",
101
101
  "tsx": "^4.20.5",
102
102
  "typedoc": "^0.28.13",
@@ -0,0 +1,85 @@
1
+ import { Arr, Result } from 'ts-data-forge';
2
+ import { type Type } from '../type.mjs';
3
+ import {
4
+ createAssertFn,
5
+ createCastFn,
6
+ createIsFn,
7
+ createPrimitiveValidationError,
8
+ prependIndexToValidationErrors,
9
+ type ValidationError,
10
+ type ValidationErrorWithMessage,
11
+ } from '../utils/index.mjs';
12
+
13
+ export const arrayAtLeastLength = <A, N extends SmallUint>(
14
+ size: N,
15
+ elementType: Type<A>,
16
+ options?: PartialReadonly<{
17
+ typeName: string;
18
+ defaultValue: ArrayAtLeastLen<N, A>;
19
+ }>,
20
+ ): Type<ArrayAtLeastLen<N, A>> => {
21
+ type T = ArrayAtLeastLen<N, A>;
22
+
23
+ const {
24
+ typeName = `ArrayAtLeastLen<${size}, ${elementType.typeName}>`,
25
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
26
+ defaultValue = Arr.create(size, elementType.defaultValue) as T,
27
+ } = options ?? {};
28
+
29
+ const validate: Type<T>['validate'] = (a) => {
30
+ if (!Arr.isArray(a)) {
31
+ return Result.err([
32
+ createPrimitiveValidationError({
33
+ actualValue: a,
34
+ expectedType: 'array',
35
+ typeName,
36
+ }),
37
+ ]);
38
+ }
39
+
40
+ if (a.length < size) {
41
+ return Result.err([
42
+ {
43
+ path: [],
44
+ actualValue: a,
45
+ expectedType: typeName,
46
+ message: `Expected array of length ${size} or more, got length ${a.length}`,
47
+ typeName,
48
+ } satisfies ValidationErrorWithMessage,
49
+ ]);
50
+ }
51
+
52
+ const errors: readonly ValidationError[] = Arr.generate(function* () {
53
+ for (const [index, el] of a.entries()) {
54
+ const res = elementType.validate(el);
55
+ if (Result.isErr(res)) {
56
+ yield* prependIndexToValidationErrors(res.value, index);
57
+ }
58
+ }
59
+ });
60
+
61
+ if (errors.length > 0) {
62
+ return Result.err(errors);
63
+ }
64
+
65
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
66
+ return Result.ok(a as unknown as T);
67
+ };
68
+
69
+ const fill: Type<T>['fill'] = (a) =>
70
+ Arr.isArray(a)
71
+ ? // TODO: remove as
72
+ // eslint-disable-next-line total-functions/no-unsafe-type-assertion
73
+ (Arr.map(Arr.seq(size), (i) => elementType.fill(a[i]) satisfies A) as T)
74
+ : defaultValue;
75
+
76
+ return {
77
+ typeName,
78
+ defaultValue,
79
+ fill,
80
+ validate,
81
+ is: createIsFn(validate),
82
+ cast: createCastFn(validate),
83
+ assertIs: createAssertFn(validate),
84
+ };
85
+ };
@@ -0,0 +1,197 @@
1
+ import { expectType, Result } from 'ts-data-forge';
2
+ import { number } from '../primitives/index.mjs';
3
+ import { type TypeOf } from '../type.mjs';
4
+ import {
5
+ type ValidationError,
6
+ validationErrorsToMessages,
7
+ } from '../utils/index.mjs';
8
+ import { arrayAtLeastLength } from './array-at-least-length.mjs';
9
+
10
+ describe('arrayAtLeastLength', () => {
11
+ describe('arg patterns', () => {
12
+ test('without explicit default value', () => {
13
+ expect(arrayAtLeastLength(3, number()).defaultValue).toStrictEqual([0, 0, 0]);
14
+ });
15
+
16
+ test('with explicit element default value', () => {
17
+ expect(arrayAtLeastLength(2, number(5)).defaultValue).toStrictEqual([5, 5]);
18
+ });
19
+
20
+ test('with explicit default value override', () => {
21
+ expect(
22
+ arrayAtLeastLength(3, number(), {
23
+ typeName: 'ys',
24
+ defaultValue: [1, 2, 3, 4],
25
+ }).defaultValue,
26
+ ).toStrictEqual([1, 2, 3, 4]);
27
+ });
28
+ });
29
+
30
+ const xs = arrayAtLeastLength(3, number(), {
31
+ typeName: 'xs',
32
+ defaultValue: [1, 2, 3],
33
+ });
34
+
35
+ type Xs = TypeOf<typeof xs>;
36
+
37
+ expectType<Xs, ArrayAtLeastLen<3, number>>('=');
38
+
39
+ expectType<typeof xs.defaultValue, Xs>('=');
40
+
41
+ describe('is', () => {
42
+ test('truthy case', () => {
43
+ const ys: unknown = [4, 5, 6, 7];
44
+
45
+ if (xs.is(ys)) {
46
+ expectType<typeof ys, Xs>('=');
47
+ } else {
48
+ expectType<typeof ys, unknown>('=');
49
+ }
50
+
51
+ expect(xs.is(ys)).toBe(true);
52
+ });
53
+
54
+ test('falsy case 1', () => {
55
+ const ys: unknown = [1, 2];
56
+
57
+ if (xs.is(ys)) {
58
+ expectType<typeof ys, Xs>('=');
59
+ } else {
60
+ expectType<typeof ys, unknown>('=');
61
+ }
62
+
63
+ expect(xs.is(ys)).toBe(false);
64
+ });
65
+
66
+ test('falsy case 2', () => {
67
+ const ys: unknown = [1, '2', 3];
68
+
69
+ if (xs.is(ys)) {
70
+ expectType<typeof ys, Xs>('=');
71
+ } else {
72
+ expectType<typeof ys, unknown>('=');
73
+ }
74
+
75
+ expect(xs.is(ys)).toBe(false);
76
+ });
77
+
78
+ test('falsy case 3', () => {
79
+ const ys: unknown = 'foo';
80
+
81
+ if (xs.is(ys)) {
82
+ expectType<typeof ys, Xs>('=');
83
+ } else {
84
+ expectType<typeof ys, unknown>('=');
85
+ }
86
+
87
+ expect(xs.is(ys)).toBe(false);
88
+ });
89
+ });
90
+
91
+ describe('validate', () => {
92
+ test('truthy case', () => {
93
+ const ys: unknown = [4, 5, 6, 7];
94
+
95
+ const result = xs.validate(ys);
96
+ expectType<typeof result, Result<Xs, readonly ValidationError[]>>('=');
97
+ expect(Result.isOk(result)).toBe(true);
98
+
99
+ const resultValue = Result.unwrapThrow(result);
100
+ expect(resultValue).toStrictEqual([4, 5, 6, 7]);
101
+ });
102
+
103
+ test('validate returns input as-is for OK cases', () => {
104
+ const input = [4, 5, 6];
105
+ const result = xs.validate(input);
106
+ expect(Result.isOk(result)).toBe(true);
107
+ const resultValue1 = Result.unwrapThrow(result);
108
+ expect(resultValue1).toBe(input); // ✅ same reference
109
+ });
110
+
111
+ test('falsy case 1', () => {
112
+ const ys: unknown = 'foo';
113
+
114
+ const result = xs.validate(ys);
115
+ expect(Result.isErr(result)).toBe(true);
116
+
117
+ const resultError = Result.unwrapErrThrow(result);
118
+ expect(resultError).toStrictEqual([
119
+ {
120
+ path: [],
121
+ actualValue: ys,
122
+ expectedType: 'array',
123
+ typeName: 'xs',
124
+ message: undefined,
125
+ },
126
+ ]);
127
+
128
+ expect(validationErrorsToMessages(resultError)).toStrictEqual([
129
+ 'Expected <array>, got <string> type value "foo".',
130
+ ]);
131
+ });
132
+
133
+ test('falsy case 2', () => {
134
+ const ys: unknown = [1, 2];
135
+
136
+ const result = xs.validate(ys);
137
+ expect(Result.isErr(result)).toBe(true);
138
+
139
+ const resultError = Result.unwrapErrThrow(result);
140
+ expect(resultError).toStrictEqual([
141
+ {
142
+ path: [],
143
+ actualValue: ys,
144
+ expectedType: 'xs',
145
+ typeName: 'xs',
146
+ message: 'Expected array of length 3 or more, got length 2',
147
+ },
148
+ ]);
149
+
150
+ expect(validationErrorsToMessages(resultError)).toStrictEqual([
151
+ 'Expected array of length 3 or more, got length 2',
152
+ ]);
153
+ });
154
+
155
+ test('falsy case 3', () => {
156
+ const ys: unknown = [1, '2', 3];
157
+
158
+ const result = xs.validate(ys);
159
+ expect(Result.isErr(result)).toBe(true);
160
+
161
+ const resultError = Result.unwrapErrThrow(result);
162
+ expect(resultError).toStrictEqual([
163
+ {
164
+ path: ['1'],
165
+ actualValue: '2',
166
+ expectedType: 'number',
167
+ typeName: 'number',
168
+ message: undefined,
169
+ },
170
+ ]);
171
+
172
+ expect(validationErrorsToMessages(resultError)).toStrictEqual([
173
+ 'Expected <number> at 1, got <string> type value "2".',
174
+ ]);
175
+ });
176
+ });
177
+
178
+ describe('fill', () => {
179
+ test('keeps numeric entries and trims extras', () => {
180
+ const ys: unknown = [4, 5, 6, 7];
181
+
182
+ expect(xs.fill(ys)).toStrictEqual([4, 5, 6]);
183
+ });
184
+
185
+ test('fills missing or invalid entries', () => {
186
+ const ys: unknown = [4, '5'];
187
+
188
+ expect(xs.fill(ys)).toStrictEqual([4, 0, 0]);
189
+ });
190
+
191
+ test('fill with the default value for non-array input', () => {
192
+ const ys: unknown = null;
193
+
194
+ expect(xs.fill(ys)).toStrictEqual([1, 2, 3]);
195
+ });
196
+ });
197
+ });
@@ -1,3 +1,4 @@
1
+ export * from './array-at-least-length.mjs';
1
2
  export * from './array-of-length.mjs';
2
3
  export * from './array.mjs';
3
4
  export * from './non-empty-array.mjs';