ts-data-forge 9.0.1 → 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.
- package/README.md +1 -1
- package/dist/array/impl/array-utils-creation.d.mts +4 -4
- package/dist/array/impl/array-utils-creation.d.mts.map +1 -1
- package/dist/array/impl/array-utils-creation.mjs.map +1 -1
- package/dist/array/impl/array-utils-element-access.d.mts +4 -4
- package/dist/array/impl/array-utils-element-access.mjs.map +1 -1
- package/dist/array/impl/array-utils-length-bounded-array-cast.d.mts +117 -0
- package/dist/array/impl/array-utils-length-bounded-array-cast.d.mts.map +1 -0
- package/dist/array/impl/array-utils-length-bounded-array-cast.mjs +37 -0
- package/dist/array/impl/array-utils-length-bounded-array-cast.mjs.map +1 -0
- package/dist/array/impl/array-utils-length-bounded-array-guard.d.mts +159 -0
- package/dist/array/impl/array-utils-length-bounded-array-guard.d.mts.map +1 -0
- package/dist/array/impl/array-utils-length-bounded-array-guard.mjs +7 -0
- package/dist/array/impl/array-utils-length-bounded-array-guard.mjs.map +1 -0
- package/dist/array/impl/array-utils-modification.d.mts +11 -11
- package/dist/array/impl/array-utils-modification.d.mts.map +1 -1
- package/dist/array/impl/array-utils-modification.mjs.map +1 -1
- package/dist/array/impl/array-utils-reducing-value.d.mts +9 -9
- package/dist/array/impl/array-utils-reducing-value.mjs.map +1 -1
- package/dist/array/impl/array-utils-size.d.mts +3 -3
- package/dist/array/impl/array-utils-size.mjs.map +1 -1
- package/dist/array/impl/array-utils-slicing.d.mts +9 -9
- package/dist/array/impl/array-utils-slicing.d.mts.map +1 -1
- package/dist/array/impl/array-utils-slicing.mjs.map +1 -1
- package/dist/array/impl/array-utils-transformation.d.mts +16 -10
- package/dist/array/impl/array-utils-transformation.d.mts.map +1 -1
- package/dist/array/impl/array-utils-transformation.mjs.map +1 -1
- package/dist/array/impl/array-utils-validation.d.mts +17 -17
- package/dist/array/impl/array-utils-validation.d.mts.map +1 -1
- package/dist/array/impl/array-utils-validation.mjs +5 -5
- package/dist/array/impl/array-utils-validation.mjs.map +1 -1
- package/dist/array/impl/index.d.mts +2 -0
- package/dist/array/impl/index.d.mts.map +1 -1
- package/dist/array/impl/index.mjs +3 -1
- package/dist/array/impl/index.mjs.map +1 -1
- package/dist/entry-point.mjs +1 -1
- package/dist/guard/index.d.mts +0 -1
- package/dist/guard/index.d.mts.map +1 -1
- package/dist/guard/index.mjs +0 -1
- package/dist/guard/index.mjs.map +1 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/string/index.d.mts +2 -0
- package/dist/string/index.d.mts.map +1 -0
- package/dist/string/index.mjs +2 -0
- package/dist/string/index.mjs.map +1 -0
- package/dist/string/str.d.mts +273 -0
- package/dist/string/str.d.mts.map +1 -0
- package/dist/string/str.mjs +42 -0
- package/dist/string/str.mjs.map +1 -0
- package/package.json +30 -92
- package/src/array/impl/array-utils-creation.mts +5 -4
- package/src/array/impl/array-utils-element-access.mts +3 -3
- package/src/array/impl/array-utils-element-access.test.mts +3 -3
- package/src/array/impl/array-utils-length-bounded-array-cast.mts +190 -0
- package/src/array/impl/array-utils-length-bounded-array-cast.test.mts +118 -0
- package/src/array/impl/array-utils-length-bounded-array-guard.mts +195 -0
- package/src/array/impl/array-utils-length-bounded-array-guard.test.mts +169 -0
- package/src/array/impl/array-utils-modification.mts +16 -15
- package/src/array/impl/array-utils-modification.test.mts +10 -5
- package/src/array/impl/array-utils-reducing-value.mts +9 -9
- package/src/array/impl/array-utils-size.mts +2 -2
- package/src/array/impl/array-utils-slicing.mts +24 -13
- package/src/array/impl/array-utils-transformation.mts +22 -16
- package/src/array/impl/array-utils-transformation.test.mts +19 -19
- package/src/array/impl/array-utils-validation.mts +24 -24
- package/src/array/impl/array-utils-validation.test.mts +94 -92
- package/src/array/impl/index.mts +2 -0
- package/src/collections/queue.test.mts +1 -1
- package/src/guard/index.mts +0 -1
- package/src/index.mts +1 -0
- package/src/object/object.test.mts +3 -3
- package/src/string/index.mts +1 -0
- package/src/string/str.mts +371 -0
- package/src/string/str.test.mts +215 -0
- package/dist/guard/is-length-bounded-string.d.mts +0 -164
- package/dist/guard/is-length-bounded-string.d.mts.map +0 -1
- package/dist/guard/is-length-bounded-string.mjs +0 -7
- package/dist/guard/is-length-bounded-string.mjs.map +0 -1
- package/src/guard/is-length-bounded-string.mts +0 -199
- package/src/guard/is-length-bounded-string.test.mts +0 -170
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type
|
|
2
|
+
type FixedLengthTuple,
|
|
3
3
|
type Increment,
|
|
4
4
|
type IsFixedLengthList,
|
|
5
5
|
type NonEmptyArray,
|
|
6
|
+
type NonEmptyTuple,
|
|
6
7
|
} from 'ts-type-forge';
|
|
7
8
|
import { asPositiveUint32 } from '../../number/index.mjs';
|
|
8
9
|
import { castMutable } from '../../others/index.mjs';
|
|
@@ -32,7 +33,7 @@ export function set<const Ar extends readonly unknown[], const V = Ar[number]>(
|
|
|
32
33
|
newValue: V,
|
|
33
34
|
): IsFixedLengthList<Ar> extends true
|
|
34
35
|
? Readonly<{ [K in keyof Ar]: Ar[K] | V }>
|
|
35
|
-
: Ar extends
|
|
36
|
+
: Ar extends NonEmptyTuple<unknown>
|
|
36
37
|
? NonEmptyArray<Ar[number] | V>
|
|
37
38
|
: readonly (Ar[number] | V)[];
|
|
38
39
|
|
|
@@ -44,7 +45,7 @@ export function set<const V>(
|
|
|
44
45
|
array: Ar,
|
|
45
46
|
) => IsFixedLengthList<Ar> extends true
|
|
46
47
|
? Readonly<{ [K in keyof Ar]: Ar[K] | V }>
|
|
47
|
-
: Ar extends
|
|
48
|
+
: Ar extends NonEmptyTuple<unknown>
|
|
48
49
|
? NonEmptyArray<Ar[number] | V>
|
|
49
50
|
: readonly (Ar[number] | V)[];
|
|
50
51
|
|
|
@@ -97,7 +98,7 @@ export function toUpdated<
|
|
|
97
98
|
updater: (prev: Ar[number]) => V,
|
|
98
99
|
): IsFixedLengthList<Ar> extends true
|
|
99
100
|
? Readonly<{ [K in keyof Ar]: Ar[K] | V }>
|
|
100
|
-
: Ar extends
|
|
101
|
+
: Ar extends NonEmptyTuple<unknown>
|
|
101
102
|
? NonEmptyArray<Ar[number] | V>
|
|
102
103
|
: readonly (Ar[number] | V)[];
|
|
103
104
|
|
|
@@ -109,7 +110,7 @@ export function toUpdated<E, const V = E>(
|
|
|
109
110
|
array: Ar,
|
|
110
111
|
) => IsFixedLengthList<Ar> extends true
|
|
111
112
|
? Readonly<{ [K in keyof Ar]: Ar[K] | V }>
|
|
112
|
-
: Ar extends
|
|
113
|
+
: Ar extends NonEmptyTuple<unknown>
|
|
113
114
|
? NonEmptyArray<Ar[number] | V>
|
|
114
115
|
: readonly (Ar[number] | V)[];
|
|
115
116
|
|
|
@@ -163,7 +164,7 @@ export function toInserted<
|
|
|
163
164
|
index: ArgArrayIndexWithNegative<Ar>,
|
|
164
165
|
newValue: V,
|
|
165
166
|
): IsFixedLengthList<Ar> extends true
|
|
166
|
-
?
|
|
167
|
+
? FixedLengthTuple<CastToNumber<Increment<Ar['length']>>, Ar[number] | V>
|
|
167
168
|
: NonEmptyArray<Ar[number] | V>;
|
|
168
169
|
|
|
169
170
|
// curried version
|
|
@@ -173,7 +174,7 @@ export function toInserted<const V>(
|
|
|
173
174
|
): <const Ar extends readonly unknown[]>(
|
|
174
175
|
array: Ar,
|
|
175
176
|
) => IsFixedLengthList<Ar> extends true
|
|
176
|
-
?
|
|
177
|
+
? FixedLengthTuple<CastToNumber<Increment<Ar['length']>>, Ar[number] | V>
|
|
177
178
|
: NonEmptyArray<Ar[number] | V>;
|
|
178
179
|
|
|
179
180
|
export function toInserted<E, const V = E>(
|
|
@@ -367,8 +368,8 @@ export function toFilled<const Ar extends readonly unknown[], const V>(
|
|
|
367
368
|
array: Ar,
|
|
368
369
|
value: V,
|
|
369
370
|
): IsFixedLengthList<Ar> extends true
|
|
370
|
-
?
|
|
371
|
-
: Ar extends
|
|
371
|
+
? FixedLengthTuple<Ar['length'], V>
|
|
372
|
+
: Ar extends NonEmptyTuple<unknown>
|
|
372
373
|
? NonEmptyArray<V>
|
|
373
374
|
: readonly V[];
|
|
374
375
|
|
|
@@ -378,8 +379,8 @@ export function toFilled<const V>(
|
|
|
378
379
|
): <const Ar extends readonly unknown[]>(
|
|
379
380
|
array: Ar,
|
|
380
381
|
) => IsFixedLengthList<Ar> extends true
|
|
381
|
-
?
|
|
382
|
-
: Ar extends
|
|
382
|
+
? FixedLengthTuple<Ar['length'], V>
|
|
383
|
+
: Ar extends NonEmptyTuple<unknown>
|
|
383
384
|
? NonEmptyArray<V>
|
|
384
385
|
: readonly V[];
|
|
385
386
|
|
|
@@ -426,8 +427,8 @@ export function toRangeFilled<const Ar extends readonly unknown[], const V>(
|
|
|
426
427
|
end: ArgArrayIndexWithNegative<Ar>,
|
|
427
428
|
],
|
|
428
429
|
): IsFixedLengthList<Ar> extends true
|
|
429
|
-
?
|
|
430
|
-
: Ar extends
|
|
430
|
+
? FixedLengthTuple<Ar['length'], V | Ar[number]>
|
|
431
|
+
: Ar extends NonEmptyTuple<unknown>
|
|
431
432
|
? NonEmptyArray<V | Ar[number]>
|
|
432
433
|
: readonly (V | Ar[number])[];
|
|
433
434
|
|
|
@@ -441,8 +442,8 @@ export function toRangeFilled<const V>(
|
|
|
441
442
|
): <const Ar extends readonly unknown[]>(
|
|
442
443
|
array: Ar,
|
|
443
444
|
) => IsFixedLengthList<Ar> extends true
|
|
444
|
-
?
|
|
445
|
-
: Ar extends
|
|
445
|
+
? FixedLengthTuple<Ar['length'], V | Ar[number]>
|
|
446
|
+
: Ar extends NonEmptyTuple<unknown>
|
|
446
447
|
? NonEmptyArray<V | Ar[number]>
|
|
447
448
|
: readonly (V | Ar[number])[];
|
|
448
449
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type FixedLengthTuple, type NonEmptyArray } from 'ts-type-forge';
|
|
2
2
|
import { expectType } from '../../expect-type.mjs';
|
|
3
3
|
import { asUint32 } from '../../number/index.mjs';
|
|
4
4
|
import {
|
|
@@ -18,7 +18,7 @@ describe('Arr modifications', () => {
|
|
|
18
18
|
|
|
19
19
|
const result = toUpdated(xs, 1, (x) => x + 2);
|
|
20
20
|
|
|
21
|
-
expectType<typeof result,
|
|
21
|
+
expectType<typeof result, FixedLengthTuple<3, number>>('=');
|
|
22
22
|
|
|
23
23
|
test('case 1', () => {
|
|
24
24
|
assert.deepStrictEqual(result, [1, 4, 3]);
|
|
@@ -39,7 +39,7 @@ describe('Arr modifications', () => {
|
|
|
39
39
|
test('case 1', () => {
|
|
40
40
|
const result = toInserted(xs, 1, 5);
|
|
41
41
|
|
|
42
|
-
expectType<typeof result,
|
|
42
|
+
expectType<typeof result, FixedLengthTuple<4, 1 | 2 | 3 | 5>>('=');
|
|
43
43
|
|
|
44
44
|
assert.deepStrictEqual(result, [1, 5, 2, 3]);
|
|
45
45
|
});
|
|
@@ -47,7 +47,7 @@ describe('Arr modifications', () => {
|
|
|
47
47
|
test('case 2 (insert head)', () => {
|
|
48
48
|
const result = toInserted(xs, 0, 5);
|
|
49
49
|
|
|
50
|
-
expectType<typeof result,
|
|
50
|
+
expectType<typeof result, FixedLengthTuple<4, 1 | 2 | 3 | 5>>('=');
|
|
51
51
|
|
|
52
52
|
assert.deepStrictEqual(result, [5, 1, 2, 3]);
|
|
53
53
|
});
|
|
@@ -61,7 +61,12 @@ describe('Arr modifications', () => {
|
|
|
61
61
|
|
|
62
62
|
expectType<typeof result, NonEmptyArray<string | 5>>('=');
|
|
63
63
|
|
|
64
|
-
assert.deepStrictEqual(result, [
|
|
64
|
+
assert.deepStrictEqual<readonly (5 | string)[]>(result, [
|
|
65
|
+
'a',
|
|
66
|
+
'b',
|
|
67
|
+
'c',
|
|
68
|
+
5,
|
|
69
|
+
]);
|
|
65
70
|
});
|
|
66
71
|
|
|
67
72
|
test('should work with curried version', () => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isError } from '@sindresorhus/is';
|
|
2
|
-
import { type Int, type
|
|
2
|
+
import { type Int, type NonEmptyTuple, type Uint } from 'ts-type-forge';
|
|
3
3
|
import { IMap } from '../../collections/index.mjs';
|
|
4
4
|
import { Optional, Result } from '../../functional/index.mjs';
|
|
5
5
|
import { isString, isUndefined } from '../../guard/index.mjs';
|
|
@@ -40,12 +40,12 @@ export function min<const Ar extends readonly number[]>(
|
|
|
40
40
|
array: Ar,
|
|
41
41
|
// If the array elements are numbers, comparator is optional.
|
|
42
42
|
comparator?: (x: Ar[number], y: Ar[number]) => number,
|
|
43
|
-
): Ar extends
|
|
43
|
+
): Ar extends NonEmptyTuple<unknown> ? Some<Ar[number]> : Optional<Ar[number]>;
|
|
44
44
|
|
|
45
45
|
export function min<const Ar extends readonly unknown[]>(
|
|
46
46
|
array: Ar,
|
|
47
47
|
comparator: (x: Ar[number], y: Ar[number]) => number,
|
|
48
|
-
): Ar extends
|
|
48
|
+
): Ar extends NonEmptyTuple<unknown> ? Some<Ar[number]> : Optional<Ar[number]>;
|
|
49
49
|
|
|
50
50
|
export function min<E extends number>(
|
|
51
51
|
array: readonly E[],
|
|
@@ -86,12 +86,12 @@ export function max<const Ar extends readonly number[]>(
|
|
|
86
86
|
array: Ar,
|
|
87
87
|
// If the array elements are numbers, comparator is optional.
|
|
88
88
|
comparator?: (x: Ar[number], y: Ar[number]) => number,
|
|
89
|
-
): Ar extends
|
|
89
|
+
): Ar extends NonEmptyTuple<unknown> ? Some<Ar[number]> : Optional<Ar[number]>;
|
|
90
90
|
|
|
91
91
|
export function max<const Ar extends readonly unknown[]>(
|
|
92
92
|
array: Ar,
|
|
93
93
|
comparator: (x: Ar[number], y: Ar[number]) => number,
|
|
94
|
-
): Ar extends
|
|
94
|
+
): Ar extends NonEmptyTuple<unknown> ? Some<Ar[number]> : Optional<Ar[number]>;
|
|
95
95
|
|
|
96
96
|
export function max<E extends number>(
|
|
97
97
|
array: readonly E[],
|
|
@@ -132,13 +132,13 @@ export function minBy<const Ar extends readonly unknown[]>(
|
|
|
132
132
|
array: Ar,
|
|
133
133
|
// If the array elements are mapped to numbers, comparator is optional.
|
|
134
134
|
comparatorValueMapper: (value: Ar[number]) => number,
|
|
135
|
-
): Ar extends
|
|
135
|
+
): Ar extends NonEmptyTuple<unknown> ? Some<Ar[number]> : Optional<Ar[number]>;
|
|
136
136
|
|
|
137
137
|
export function minBy<const Ar extends readonly unknown[], V>(
|
|
138
138
|
array: Ar,
|
|
139
139
|
comparatorValueMapper: (value: Ar[number]) => V,
|
|
140
140
|
comparator: (x: V, y: V) => number,
|
|
141
|
-
): Ar extends
|
|
141
|
+
): Ar extends NonEmptyTuple<unknown> ? Some<Ar[number]> : Optional<Ar[number]>;
|
|
142
142
|
|
|
143
143
|
export function minBy<E, V>(
|
|
144
144
|
array: readonly E[],
|
|
@@ -184,13 +184,13 @@ export function maxBy<const Ar extends readonly unknown[]>(
|
|
|
184
184
|
array: Ar,
|
|
185
185
|
// If the array elements are mapped to numbers, comparator is optional.
|
|
186
186
|
comparatorValueMapper: (value: Ar[number]) => number,
|
|
187
|
-
): Ar extends
|
|
187
|
+
): Ar extends NonEmptyTuple<unknown> ? Some<Ar[number]> : Optional<Ar[number]>;
|
|
188
188
|
|
|
189
189
|
export function maxBy<const Ar extends readonly unknown[], V>(
|
|
190
190
|
array: Ar,
|
|
191
191
|
comparatorValueMapper: (value: Ar[number]) => V,
|
|
192
192
|
comparator: (x: V, y: V) => number,
|
|
193
|
-
): Ar extends
|
|
193
|
+
): Ar extends NonEmptyTuple<unknown> ? Some<Ar[number]> : Optional<Ar[number]>;
|
|
194
194
|
|
|
195
195
|
export function maxBy<E, V>(
|
|
196
196
|
array: readonly E[],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type IntersectBrand,
|
|
3
|
-
type
|
|
3
|
+
type NonEmptyTuple,
|
|
4
4
|
type PositiveNumber,
|
|
5
5
|
} from 'ts-type-forge';
|
|
6
6
|
/**
|
|
@@ -26,7 +26,7 @@ import { type SizeType } from '../../types.mjs';
|
|
|
26
26
|
|
|
27
27
|
export const size = <const Ar extends readonly unknown[]>(
|
|
28
28
|
array: Ar,
|
|
29
|
-
): Ar extends
|
|
29
|
+
): Ar extends NonEmptyTuple<unknown>
|
|
30
30
|
? IntersectBrand<PositiveNumber, SizeType.Arr>
|
|
31
31
|
: SizeType.Arr =>
|
|
32
32
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
type List,
|
|
3
|
+
type NonEmptyArray,
|
|
4
|
+
type NonEmptyTuple,
|
|
5
|
+
type StructuralPrefixLength,
|
|
6
|
+
} from 'ts-type-forge';
|
|
2
7
|
import { Uint32 } from '../../number/index.mjs';
|
|
3
8
|
import { type SizeType } from '../../types.mjs';
|
|
4
9
|
import { size } from './array-utils-size.mjs';
|
|
@@ -84,10 +89,10 @@ export function take<
|
|
|
84
89
|
>(
|
|
85
90
|
array: Ar,
|
|
86
91
|
num: N,
|
|
87
|
-
): N extends
|
|
92
|
+
): N extends StructuralPrefixLength
|
|
88
93
|
? List.Take<N, Ar>
|
|
89
94
|
: N extends SizeType.ArgArrPositive
|
|
90
|
-
? Ar extends
|
|
95
|
+
? Ar extends NonEmptyTuple<unknown>
|
|
91
96
|
? NonEmptyArray<Ar[number]>
|
|
92
97
|
: readonly Ar[number][]
|
|
93
98
|
: readonly Ar[number][];
|
|
@@ -96,10 +101,10 @@ export function take<N extends SizeType.ArgArr>(
|
|
|
96
101
|
num: N,
|
|
97
102
|
): <const Ar extends readonly unknown[]>(
|
|
98
103
|
array: Ar,
|
|
99
|
-
) => N extends
|
|
104
|
+
) => N extends StructuralPrefixLength
|
|
100
105
|
? List.Take<N, Ar>
|
|
101
106
|
: N extends SizeType.ArgArrPositive
|
|
102
|
-
? Ar extends
|
|
107
|
+
? Ar extends NonEmptyTuple<unknown>
|
|
103
108
|
? NonEmptyArray<Ar[number]>
|
|
104
109
|
: readonly Ar[number][]
|
|
105
110
|
: readonly Ar[number][];
|
|
@@ -147,10 +152,10 @@ export function takeLast<
|
|
|
147
152
|
>(
|
|
148
153
|
array: Ar,
|
|
149
154
|
num: N,
|
|
150
|
-
): N extends
|
|
155
|
+
): N extends StructuralPrefixLength
|
|
151
156
|
? List.TakeLast<N, Ar>
|
|
152
157
|
: N extends SizeType.ArgArrPositive
|
|
153
|
-
? Ar extends
|
|
158
|
+
? Ar extends NonEmptyTuple<unknown>
|
|
154
159
|
? NonEmptyArray<Ar[number]>
|
|
155
160
|
: readonly Ar[number][]
|
|
156
161
|
: readonly Ar[number][];
|
|
@@ -159,10 +164,10 @@ export function takeLast<N extends SizeType.ArgArr>(
|
|
|
159
164
|
num: N,
|
|
160
165
|
): <const Ar extends readonly unknown[]>(
|
|
161
166
|
array: Ar,
|
|
162
|
-
) => N extends
|
|
167
|
+
) => N extends StructuralPrefixLength
|
|
163
168
|
? List.TakeLast<N, Ar>
|
|
164
169
|
: N extends SizeType.ArgArrPositive
|
|
165
|
-
? Ar extends
|
|
170
|
+
? Ar extends NonEmptyTuple<unknown>
|
|
166
171
|
? NonEmptyArray<Ar[number]>
|
|
167
172
|
: readonly Ar[number][]
|
|
168
173
|
: readonly Ar[number][];
|
|
@@ -210,14 +215,16 @@ export function skip<
|
|
|
210
215
|
>(
|
|
211
216
|
array: Ar,
|
|
212
217
|
num: N,
|
|
213
|
-
): N extends
|
|
218
|
+
): N extends StructuralPrefixLength ? List.Skip<N, Ar> : readonly Ar[number][];
|
|
214
219
|
|
|
215
220
|
// curried version
|
|
216
221
|
export function skip<N extends SizeType.ArgArr>(
|
|
217
222
|
num: N,
|
|
218
223
|
): <const Ar extends readonly unknown[]>(
|
|
219
224
|
array: Ar,
|
|
220
|
-
) => N extends
|
|
225
|
+
) => N extends StructuralPrefixLength
|
|
226
|
+
? List.Skip<N, Ar>
|
|
227
|
+
: readonly Ar[number][];
|
|
221
228
|
|
|
222
229
|
export function skip<E>(
|
|
223
230
|
...args: readonly [readonly E[], SizeType.ArgArr] | readonly [SizeType.ArgArr]
|
|
@@ -260,14 +267,18 @@ export function skipLast<
|
|
|
260
267
|
>(
|
|
261
268
|
array: Ar,
|
|
262
269
|
num: N,
|
|
263
|
-
): N extends
|
|
270
|
+
): N extends StructuralPrefixLength
|
|
271
|
+
? List.SkipLast<N, Ar>
|
|
272
|
+
: readonly Ar[number][];
|
|
264
273
|
|
|
265
274
|
// curried version
|
|
266
275
|
export function skipLast<N extends SizeType.ArgArr>(
|
|
267
276
|
num: N,
|
|
268
277
|
): <const Ar extends readonly unknown[]>(
|
|
269
278
|
array: Ar,
|
|
270
|
-
) => N extends
|
|
279
|
+
) => N extends StructuralPrefixLength
|
|
280
|
+
? List.SkipLast<N, Ar>
|
|
281
|
+
: readonly Ar[number][];
|
|
271
282
|
|
|
272
283
|
export function skipLast<E>(
|
|
273
284
|
...args:
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type
|
|
2
|
+
type FixedLengthTuple,
|
|
3
3
|
type IsFixedLengthList,
|
|
4
4
|
type List,
|
|
5
|
-
type MutableNonEmptyArray,
|
|
6
5
|
type NonEmptyArray,
|
|
6
|
+
type NonEmptyTuple,
|
|
7
7
|
type PositiveInt,
|
|
8
8
|
type PositiveUint32,
|
|
9
9
|
type Primitive,
|
|
@@ -98,9 +98,12 @@ export function map<A, B>(
|
|
|
98
98
|
*
|
|
99
99
|
* const expectedCurriedTotals = [10, 5, 20] as const;
|
|
100
100
|
*
|
|
101
|
-
* assert.deepStrictEqual(runningTotals, expectedTotals);
|
|
101
|
+
* assert.deepStrictEqual<readonly number[]>(runningTotals, expectedTotals);
|
|
102
102
|
*
|
|
103
|
-
* assert.deepStrictEqual(
|
|
103
|
+
* assert.deepStrictEqual<readonly number[]>(
|
|
104
|
+
* runningTotalsFromCurried,
|
|
105
|
+
* expectedCurriedTotals,
|
|
106
|
+
* );
|
|
104
107
|
* ```
|
|
105
108
|
*/
|
|
106
109
|
export function scan<const Ar extends readonly unknown[], S>(
|
|
@@ -137,12 +140,12 @@ export function scan<E, S>(
|
|
|
137
140
|
) => S,
|
|
138
141
|
init: S,
|
|
139
142
|
]
|
|
140
|
-
):
|
|
143
|
+
): NonEmptyTuple<S> | ((array: readonly E[]) => NonEmptyTuple<S>) {
|
|
141
144
|
switch (args.length) {
|
|
142
145
|
case 3: {
|
|
143
146
|
const [array, reducer, init] = args;
|
|
144
147
|
|
|
145
|
-
const mut_result
|
|
148
|
+
const mut_result = castMutable<NonEmptyTuple<S>>(
|
|
146
149
|
newArray<PositiveUint32, S>(asPositiveUint32(array.length + 1), init),
|
|
147
150
|
);
|
|
148
151
|
|
|
@@ -220,8 +223,8 @@ export const toSorted = <const Ar extends readonly unknown[]>(
|
|
|
220
223
|
]
|
|
221
224
|
: readonly [array: Ar, comparator: (x: Ar[number], y: Ar[number]) => number]
|
|
222
225
|
): IsFixedLengthList<Ar> extends true
|
|
223
|
-
?
|
|
224
|
-
: Ar extends
|
|
226
|
+
? FixedLengthTuple<Ar['length'], Ar[number]>
|
|
227
|
+
: Ar extends NonEmptyTuple<unknown>
|
|
225
228
|
? NonEmptyArray<Ar[number]>
|
|
226
229
|
: readonly Ar[number][] =>
|
|
227
230
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
@@ -278,8 +281,8 @@ export function toSortedBy<const Ar extends readonly unknown[]>(
|
|
|
278
281
|
// If the array elements are mapped to numbers, comparator is optional.
|
|
279
282
|
comparator?: (x: number, y: number) => number,
|
|
280
283
|
): IsFixedLengthList<Ar> extends true
|
|
281
|
-
?
|
|
282
|
-
: Ar extends
|
|
284
|
+
? FixedLengthTuple<Ar['length'], Ar[number]>
|
|
285
|
+
: Ar extends NonEmptyTuple<unknown>
|
|
283
286
|
? NonEmptyArray<Ar[number]>
|
|
284
287
|
: readonly Ar[number][];
|
|
285
288
|
|
|
@@ -288,8 +291,8 @@ export function toSortedBy<const Ar extends readonly unknown[], const V>(
|
|
|
288
291
|
comparatorValueMapper: (value: Ar[number]) => V,
|
|
289
292
|
comparator: (x: V, y: V) => number,
|
|
290
293
|
): IsFixedLengthList<Ar> extends true
|
|
291
|
-
?
|
|
292
|
-
: Ar extends
|
|
294
|
+
? FixedLengthTuple<Ar['length'], Ar[number]>
|
|
295
|
+
: Ar extends NonEmptyTuple<unknown>
|
|
293
296
|
? NonEmptyArray<Ar[number]>
|
|
294
297
|
: readonly Ar[number][];
|
|
295
298
|
|
|
@@ -434,12 +437,12 @@ export function filterNot<E>(
|
|
|
434
437
|
*
|
|
435
438
|
* const expected = ['a', 'b', 'c'] as const;
|
|
436
439
|
*
|
|
437
|
-
* assert.deepStrictEqual(uniqueLetters, expected);
|
|
440
|
+
* assert.deepStrictEqual<readonly string[]>(uniqueLetters, expected);
|
|
438
441
|
* ```
|
|
439
442
|
*/
|
|
440
443
|
export const uniq = <const Ar extends readonly Primitive[]>(
|
|
441
444
|
array: Ar,
|
|
442
|
-
): Ar extends
|
|
445
|
+
): Ar extends NonEmptyTuple<unknown>
|
|
443
446
|
? NonEmptyArray<Ar[number]>
|
|
444
447
|
: readonly Ar[number][] =>
|
|
445
448
|
// eslint-disable-next-line total-functions/no-unsafe-type-assertion
|
|
@@ -466,7 +469,10 @@ export const uniq = <const Ar extends readonly Primitive[]>(
|
|
|
466
469
|
* { id: 3, name: 'Grace' },
|
|
467
470
|
* ] as const;
|
|
468
471
|
*
|
|
469
|
-
* assert.deepStrictEqual
|
|
472
|
+
* assert.deepStrictEqual<readonly Readonly<{ id: number; name: string }>[]>(
|
|
473
|
+
* uniqueById,
|
|
474
|
+
* expected,
|
|
475
|
+
* );
|
|
470
476
|
* ```
|
|
471
477
|
*/
|
|
472
478
|
export const uniqBy = <
|
|
@@ -475,7 +481,7 @@ export const uniqBy = <
|
|
|
475
481
|
>(
|
|
476
482
|
array: Ar,
|
|
477
483
|
mapFn: (value: Ar[number]) => P,
|
|
478
|
-
): Ar extends
|
|
484
|
+
): Ar extends NonEmptyTuple<unknown>
|
|
479
485
|
? NonEmptyArray<Ar[number]>
|
|
480
486
|
: readonly Ar[number][] => {
|
|
481
487
|
const mut_mappedValues = new Set<P>();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type FixedLengthTuple } from 'ts-type-forge';
|
|
2
2
|
import { IMap } from '../../collections/index.mjs';
|
|
3
3
|
import { expectType } from '../../expect-type.mjs';
|
|
4
4
|
import { Optional } from '../../functional/index.mjs';
|
|
@@ -26,7 +26,7 @@ describe('Arr transformations', () => {
|
|
|
26
26
|
describe(map, () => {
|
|
27
27
|
const mapped = map([1, 2, 3], (x, i): number => x ** 2 * i);
|
|
28
28
|
|
|
29
|
-
expectType<typeof mapped,
|
|
29
|
+
expectType<typeof mapped, FixedLengthTuple<3, number>>('=');
|
|
30
30
|
|
|
31
31
|
test('case 1', () => {
|
|
32
32
|
assert.deepStrictEqual(mapped, [0, 4, 18]);
|
|
@@ -73,7 +73,7 @@ describe('Arr transformations', () => {
|
|
|
73
73
|
|
|
74
74
|
expectType<typeof runningSum, readonly [number, ...number[]]>('<=');
|
|
75
75
|
|
|
76
|
-
assert.deepStrictEqual(runningSum, [0, 1, 3, 6, 10]);
|
|
76
|
+
assert.deepStrictEqual<readonly number[]>(runningSum, [0, 1, 3, 6, 10]);
|
|
77
77
|
});
|
|
78
78
|
|
|
79
79
|
test('should include initial value as first element', () => {
|
|
@@ -81,7 +81,7 @@ describe('Arr transformations', () => {
|
|
|
81
81
|
|
|
82
82
|
const result = scan(numbers, (acc, curr) => acc + curr, 100);
|
|
83
83
|
|
|
84
|
-
assert.deepStrictEqual(result, [100, 110, 130, 160]);
|
|
84
|
+
assert.deepStrictEqual<readonly number[]>(result, [100, 110, 130, 160]);
|
|
85
85
|
|
|
86
86
|
expect(result).toHaveLength(4); // original length + 1
|
|
87
87
|
});
|
|
@@ -93,9 +93,9 @@ describe('Arr transformations', () => {
|
|
|
93
93
|
|
|
94
94
|
const result2 = scanSum([5, 10]);
|
|
95
95
|
|
|
96
|
-
assert.deepStrictEqual(result1, [0, 1, 3, 6]);
|
|
96
|
+
assert.deepStrictEqual<readonly number[]>(result1, [0, 1, 3, 6]);
|
|
97
97
|
|
|
98
|
-
assert.deepStrictEqual(result2, [0, 5, 15]);
|
|
98
|
+
assert.deepStrictEqual<readonly number[]>(result2, [0, 5, 15]);
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
test('should provide index to reducer', () => {
|
|
@@ -121,7 +121,7 @@ describe('Arr transformations', () => {
|
|
|
121
121
|
|
|
122
122
|
const result = scan(empty, (acc, curr) => acc + curr, 42);
|
|
123
123
|
|
|
124
|
-
assert.deepStrictEqual(result, [42]);
|
|
124
|
+
assert.deepStrictEqual<readonly number[]>(result, [42]);
|
|
125
125
|
});
|
|
126
126
|
|
|
127
127
|
test('should work with different accumulator and element types', () => {
|
|
@@ -131,7 +131,7 @@ describe('Arr transformations', () => {
|
|
|
131
131
|
|
|
132
132
|
expectType<typeof result, readonly [number, ...number[]]>('<=');
|
|
133
133
|
|
|
134
|
-
assert.deepStrictEqual(result, [0, 1, 2, 3]);
|
|
134
|
+
assert.deepStrictEqual<readonly number[]>(result, [0, 1, 2, 3]);
|
|
135
135
|
});
|
|
136
136
|
|
|
137
137
|
test('should compute running product', () => {
|
|
@@ -139,7 +139,7 @@ describe('Arr transformations', () => {
|
|
|
139
139
|
|
|
140
140
|
const runningProduct = scan(numbers, (acc, curr) => acc * curr, 1);
|
|
141
141
|
|
|
142
|
-
assert.deepStrictEqual(runningProduct, [1, 2, 6, 24]);
|
|
142
|
+
assert.deepStrictEqual<readonly number[]>(runningProduct, [1, 2, 6, 24]);
|
|
143
143
|
});
|
|
144
144
|
|
|
145
145
|
test('should work with objects', () => {
|
|
@@ -147,7 +147,7 @@ describe('Arr transformations', () => {
|
|
|
147
147
|
|
|
148
148
|
const result = scan(items, (acc, curr) => acc + curr.value, 0);
|
|
149
149
|
|
|
150
|
-
assert.deepStrictEqual(result, [0, 10, 30, 60]);
|
|
150
|
+
assert.deepStrictEqual<readonly number[]>(result, [0, 10, 30, 60]);
|
|
151
151
|
});
|
|
152
152
|
|
|
153
153
|
test('should preserve all intermediate values', () => {
|
|
@@ -156,7 +156,7 @@ describe('Arr transformations', () => {
|
|
|
156
156
|
const result = scan(numbers, (acc, curr) => acc - curr, 10);
|
|
157
157
|
|
|
158
158
|
// 10 -> 10-1=9 -> 9-2=7 -> 7-3=4
|
|
159
|
-
assert.deepStrictEqual(result, [10, 9, 7, 4]);
|
|
159
|
+
assert.deepStrictEqual<readonly number[]>(result, [10, 9, 7, 4]);
|
|
160
160
|
});
|
|
161
161
|
});
|
|
162
162
|
|
|
@@ -215,7 +215,7 @@ describe('Arr transformations', () => {
|
|
|
215
215
|
|
|
216
216
|
const result = toSorted(xs);
|
|
217
217
|
|
|
218
|
-
expectType<typeof result,
|
|
218
|
+
expectType<typeof result, FixedLengthTuple<3, 1 | 2 | 3>>('=');
|
|
219
219
|
|
|
220
220
|
test('case 1', () => {
|
|
221
221
|
assert.deepStrictEqual(result, [1, 2, 3]);
|
|
@@ -227,7 +227,7 @@ describe('Arr transformations', () => {
|
|
|
227
227
|
|
|
228
228
|
const result = toSorted(xs, (a, b) => a - b);
|
|
229
229
|
|
|
230
|
-
expectType<typeof result,
|
|
230
|
+
expectType<typeof result, FixedLengthTuple<3, 1 | 2 | 3>>('=');
|
|
231
231
|
|
|
232
232
|
test('case 2', () => {
|
|
233
233
|
assert.deepStrictEqual(result, [1, 2, 3]);
|
|
@@ -239,7 +239,7 @@ describe('Arr transformations', () => {
|
|
|
239
239
|
|
|
240
240
|
const result = toSorted(xs, (a, b) => b - a);
|
|
241
241
|
|
|
242
|
-
expectType<typeof result,
|
|
242
|
+
expectType<typeof result, FixedLengthTuple<3, 1 | 2 | 3>>('=');
|
|
243
243
|
|
|
244
244
|
test('case 3', () => {
|
|
245
245
|
assert.deepStrictEqual(result, [3, 2, 1]);
|
|
@@ -255,7 +255,7 @@ describe('Arr transformations', () => {
|
|
|
255
255
|
|
|
256
256
|
expectType<
|
|
257
257
|
typeof sorted,
|
|
258
|
-
|
|
258
|
+
FixedLengthTuple<3, Readonly<{ v: 1 } | { v: 2 } | { v: 3 }>>
|
|
259
259
|
>('=');
|
|
260
260
|
|
|
261
261
|
test('case 1', () => {
|
|
@@ -274,7 +274,7 @@ describe('Arr transformations', () => {
|
|
|
274
274
|
|
|
275
275
|
expectType<
|
|
276
276
|
typeof sorted,
|
|
277
|
-
|
|
277
|
+
FixedLengthTuple<3, Readonly<{ v: 1 } | { v: 2 } | { v: 3 }>>
|
|
278
278
|
>('=');
|
|
279
279
|
|
|
280
280
|
test('case 2', () => {
|
|
@@ -429,7 +429,7 @@ describe('Arr transformations', () => {
|
|
|
429
429
|
|
|
430
430
|
const result = uniq(array);
|
|
431
431
|
|
|
432
|
-
assert.deepStrictEqual(result, [1, 2, 3, 4]);
|
|
432
|
+
assert.deepStrictEqual<readonly number[]>(result, [1, 2, 3, 4]);
|
|
433
433
|
});
|
|
434
434
|
|
|
435
435
|
test('should work with strings', () => {
|
|
@@ -437,7 +437,7 @@ describe('Arr transformations', () => {
|
|
|
437
437
|
|
|
438
438
|
const result = uniq(array);
|
|
439
439
|
|
|
440
|
-
assert.deepStrictEqual(result, ['a', 'b', 'c']);
|
|
440
|
+
assert.deepStrictEqual<readonly string[]>(result, ['a', 'b', 'c']);
|
|
441
441
|
});
|
|
442
442
|
|
|
443
443
|
test('should work with empty array', () => {
|
|
@@ -453,7 +453,7 @@ describe('Arr transformations', () => {
|
|
|
453
453
|
|
|
454
454
|
const result = uniq(array);
|
|
455
455
|
|
|
456
|
-
assert.deepStrictEqual(result, [3, 1, 2]);
|
|
456
|
+
assert.deepStrictEqual<readonly number[]>(result, [3, 1, 2]);
|
|
457
457
|
});
|
|
458
458
|
});
|
|
459
459
|
|