@nlozgachev/pipelined 0.12.0 → 0.14.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/LICENCE +28 -0
- package/README.md +1 -1
- package/{types/src/Types/NonEmptyList.d.ts → dist/NonEmptyList-BlGFjor5.d.mts} +4 -3
- package/dist/NonEmptyList-BlGFjor5.d.ts +30 -0
- package/dist/Task-Bd3gXPRQ.d.mts +677 -0
- package/dist/Task-BjAkkD6t.d.ts +677 -0
- package/dist/chunk-4TXC322E.mjs +136 -0
- package/dist/chunk-BYWKZLHM.mjs +10 -0
- package/dist/chunk-DBIC62UV.mjs +6 -0
- package/dist/chunk-FAZN3IWZ.mjs +554 -0
- package/dist/chunk-QPTGO5AS.mjs +150 -0
- package/dist/chunk-UV2HMF2A.mjs +514 -0
- package/dist/composition.d.mts +495 -0
- package/dist/composition.d.ts +495 -0
- package/dist/composition.js +188 -0
- package/dist/composition.mjs +58 -0
- package/dist/core.d.mts +2170 -0
- package/dist/core.d.ts +2170 -0
- package/dist/core.js +698 -0
- package/dist/core.mjs +42 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1421 -0
- package/dist/index.mjs +120 -0
- package/dist/types.d.mts +54 -0
- package/{types/src/Types/Brand.d.ts → dist/types.d.ts} +6 -4
- package/dist/types.js +41 -0
- package/dist/types.mjs +10 -0
- package/dist/utils.d.mts +1285 -0
- package/dist/utils.d.ts +1285 -0
- package/dist/utils.js +722 -0
- package/dist/utils.mjs +18 -0
- package/package.json +64 -69
- package/esm/mod.js +0 -3
- package/esm/package.json +0 -3
- package/esm/src/Composition/compose.js +0 -3
- package/esm/src/Composition/converge.js +0 -3
- package/esm/src/Composition/curry.js +0 -42
- package/esm/src/Composition/flip.js +0 -20
- package/esm/src/Composition/flow.js +0 -8
- package/esm/src/Composition/fn.js +0 -85
- package/esm/src/Composition/index.js +0 -13
- package/esm/src/Composition/juxt.js +0 -3
- package/esm/src/Composition/memoize.js +0 -66
- package/esm/src/Composition/not.js +0 -25
- package/esm/src/Composition/on.js +0 -12
- package/esm/src/Composition/pipe.js +0 -3
- package/esm/src/Composition/tap.js +0 -33
- package/esm/src/Composition/uncurry.js +0 -32
- package/esm/src/Core/Deferred.js +0 -30
- package/esm/src/Core/InternalTypes.js +0 -1
- package/esm/src/Core/Lens.js +0 -98
- package/esm/src/Core/Logged.js +0 -111
- package/esm/src/Core/Option.js +0 -191
- package/esm/src/Core/Optional.js +0 -160
- package/esm/src/Core/Predicate.js +0 -133
- package/esm/src/Core/Reader.js +0 -134
- package/esm/src/Core/Refinement.js +0 -115
- package/esm/src/Core/RemoteData.js +0 -211
- package/esm/src/Core/Result.js +0 -170
- package/esm/src/Core/State.js +0 -181
- package/esm/src/Core/Task.js +0 -223
- package/esm/src/Core/TaskOption.js +0 -106
- package/esm/src/Core/TaskResult.js +0 -127
- package/esm/src/Core/TaskValidation.js +0 -128
- package/esm/src/Core/These.js +0 -245
- package/esm/src/Core/Tuple.js +0 -112
- package/esm/src/Core/Validation.js +0 -212
- package/esm/src/Core/index.js +0 -18
- package/esm/src/Types/Brand.js +0 -28
- package/esm/src/Types/NonEmptyList.js +0 -14
- package/esm/src/Types/index.js +0 -2
- package/esm/src/Utils/Arr.js +0 -570
- package/esm/src/Utils/Dict.js +0 -421
- package/esm/src/Utils/Num.js +0 -124
- package/esm/src/Utils/Rec.js +0 -241
- package/esm/src/Utils/Str.js +0 -134
- package/esm/src/Utils/Uniq.js +0 -265
- package/esm/src/Utils/index.js +0 -6
- package/script/mod.js +0 -19
- package/script/package.json +0 -3
- package/script/src/Composition/compose.js +0 -6
- package/script/src/Composition/converge.js +0 -6
- package/script/src/Composition/curry.js +0 -48
- package/script/src/Composition/flip.js +0 -24
- package/script/src/Composition/flow.js +0 -11
- package/script/src/Composition/fn.js +0 -98
- package/script/src/Composition/index.js +0 -29
- package/script/src/Composition/juxt.js +0 -6
- package/script/src/Composition/memoize.js +0 -71
- package/script/src/Composition/not.js +0 -29
- package/script/src/Composition/on.js +0 -16
- package/script/src/Composition/pipe.js +0 -6
- package/script/src/Composition/tap.js +0 -37
- package/script/src/Composition/uncurry.js +0 -38
- package/script/src/Core/Deferred.js +0 -33
- package/script/src/Core/InternalTypes.js +0 -2
- package/script/src/Core/Lens.js +0 -101
- package/script/src/Core/Logged.js +0 -114
- package/script/src/Core/Option.js +0 -194
- package/script/src/Core/Optional.js +0 -163
- package/script/src/Core/Predicate.js +0 -136
- package/script/src/Core/Reader.js +0 -137
- package/script/src/Core/Refinement.js +0 -118
- package/script/src/Core/RemoteData.js +0 -214
- package/script/src/Core/Result.js +0 -173
- package/script/src/Core/State.js +0 -184
- package/script/src/Core/Task.js +0 -226
- package/script/src/Core/TaskOption.js +0 -109
- package/script/src/Core/TaskResult.js +0 -130
- package/script/src/Core/TaskValidation.js +0 -131
- package/script/src/Core/These.js +0 -248
- package/script/src/Core/Tuple.js +0 -115
- package/script/src/Core/Validation.js +0 -215
- package/script/src/Core/index.js +0 -34
- package/script/src/Types/Brand.js +0 -31
- package/script/src/Types/NonEmptyList.js +0 -18
- package/script/src/Types/index.js +0 -18
- package/script/src/Utils/Arr.js +0 -573
- package/script/src/Utils/Dict.js +0 -424
- package/script/src/Utils/Num.js +0 -127
- package/script/src/Utils/Rec.js +0 -244
- package/script/src/Utils/Str.js +0 -137
- package/script/src/Utils/Uniq.js +0 -268
- package/script/src/Utils/index.js +0 -22
- package/types/mod.d.ts +0 -4
- package/types/mod.d.ts.map +0 -1
- package/types/src/Composition/compose.d.ts +0 -33
- package/types/src/Composition/compose.d.ts.map +0 -1
- package/types/src/Composition/converge.d.ts +0 -21
- package/types/src/Composition/converge.d.ts.map +0 -1
- package/types/src/Composition/curry.d.ts +0 -43
- package/types/src/Composition/curry.d.ts.map +0 -1
- package/types/src/Composition/flip.d.ts +0 -21
- package/types/src/Composition/flip.d.ts.map +0 -1
- package/types/src/Composition/flow.d.ts +0 -56
- package/types/src/Composition/flow.d.ts.map +0 -1
- package/types/src/Composition/fn.d.ts +0 -76
- package/types/src/Composition/fn.d.ts.map +0 -1
- package/types/src/Composition/index.d.ts +0 -14
- package/types/src/Composition/index.d.ts.map +0 -1
- package/types/src/Composition/juxt.d.ts +0 -18
- package/types/src/Composition/juxt.d.ts.map +0 -1
- package/types/src/Composition/memoize.d.ts +0 -46
- package/types/src/Composition/memoize.d.ts.map +0 -1
- package/types/src/Composition/not.d.ts +0 -26
- package/types/src/Composition/not.d.ts.map +0 -1
- package/types/src/Composition/on.d.ts +0 -13
- package/types/src/Composition/on.d.ts.map +0 -1
- package/types/src/Composition/pipe.d.ts +0 -56
- package/types/src/Composition/pipe.d.ts.map +0 -1
- package/types/src/Composition/tap.d.ts +0 -31
- package/types/src/Composition/tap.d.ts.map +0 -1
- package/types/src/Composition/uncurry.d.ts +0 -54
- package/types/src/Composition/uncurry.d.ts.map +0 -1
- package/types/src/Core/Deferred.d.ts +0 -49
- package/types/src/Core/Deferred.d.ts.map +0 -1
- package/types/src/Core/InternalTypes.d.ts +0 -23
- package/types/src/Core/InternalTypes.d.ts.map +0 -1
- package/types/src/Core/Lens.d.ts +0 -118
- package/types/src/Core/Lens.d.ts.map +0 -1
- package/types/src/Core/Logged.d.ts +0 -126
- package/types/src/Core/Logged.d.ts.map +0 -1
- package/types/src/Core/Option.d.ts +0 -209
- package/types/src/Core/Option.d.ts.map +0 -1
- package/types/src/Core/Optional.d.ts +0 -158
- package/types/src/Core/Optional.d.ts.map +0 -1
- package/types/src/Core/Predicate.d.ts +0 -161
- package/types/src/Core/Predicate.d.ts.map +0 -1
- package/types/src/Core/Reader.d.ts +0 -156
- package/types/src/Core/Reader.d.ts.map +0 -1
- package/types/src/Core/Refinement.d.ts +0 -138
- package/types/src/Core/Refinement.d.ts.map +0 -1
- package/types/src/Core/RemoteData.d.ts +0 -197
- package/types/src/Core/RemoteData.d.ts.map +0 -1
- package/types/src/Core/Result.d.ts +0 -182
- package/types/src/Core/Result.d.ts.map +0 -1
- package/types/src/Core/State.d.ts +0 -192
- package/types/src/Core/State.d.ts.map +0 -1
- package/types/src/Core/Task.d.ts +0 -219
- package/types/src/Core/Task.d.ts.map +0 -1
- package/types/src/Core/TaskOption.d.ts +0 -121
- package/types/src/Core/TaskOption.d.ts.map +0 -1
- package/types/src/Core/TaskResult.d.ts +0 -119
- package/types/src/Core/TaskResult.d.ts.map +0 -1
- package/types/src/Core/TaskValidation.d.ts +0 -144
- package/types/src/Core/TaskValidation.d.ts.map +0 -1
- package/types/src/Core/These.d.ts +0 -225
- package/types/src/Core/These.d.ts.map +0 -1
- package/types/src/Core/Tuple.d.ts +0 -129
- package/types/src/Core/Tuple.d.ts.map +0 -1
- package/types/src/Core/Validation.d.ts +0 -203
- package/types/src/Core/Validation.d.ts.map +0 -1
- package/types/src/Core/index.d.ts +0 -19
- package/types/src/Core/index.d.ts.map +0 -1
- package/types/src/Types/Brand.d.ts.map +0 -1
- package/types/src/Types/NonEmptyList.d.ts.map +0 -1
- package/types/src/Types/index.d.ts +0 -3
- package/types/src/Types/index.d.ts.map +0 -1
- package/types/src/Utils/Arr.d.ts +0 -403
- package/types/src/Utils/Arr.d.ts.map +0 -1
- package/types/src/Utils/Dict.d.ts +0 -310
- package/types/src/Utils/Dict.d.ts.map +0 -1
- package/types/src/Utils/Num.d.ts +0 -110
- package/types/src/Utils/Num.d.ts.map +0 -1
- package/types/src/Utils/Rec.d.ts +0 -159
- package/types/src/Utils/Rec.d.ts.map +0 -1
- package/types/src/Utils/Str.d.ts +0 -128
- package/types/src/Utils/Str.d.ts.map +0 -1
- package/types/src/Utils/Uniq.d.ts +0 -179
- package/types/src/Utils/Uniq.d.ts.map +0 -1
- package/types/src/Utils/index.d.ts +0 -7
- package/types/src/Utils/index.d.ts.map +0 -1
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,1285 @@
|
|
|
1
|
+
import { a as Option, R as Result, T as Task } from './Task-BjAkkD6t.js';
|
|
2
|
+
import { N as NonEmptyList } from './NonEmptyList-BlGFjor5.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Functional array utilities that compose well with pipe.
|
|
6
|
+
* All functions are data-last and curried where applicable.
|
|
7
|
+
* Safe access functions return Option instead of throwing or returning undefined.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* pipe(
|
|
12
|
+
* [1, 2, 3, 4, 5],
|
|
13
|
+
* Arr.filter(n => n > 2),
|
|
14
|
+
* Arr.map(n => n * 10),
|
|
15
|
+
* Arr.head
|
|
16
|
+
* ); // Some(30)
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
declare namespace Arr {
|
|
20
|
+
/**
|
|
21
|
+
* Returns the first element of an array, or None if the array is empty.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* Arr.head([1, 2, 3]); // Some(1)
|
|
26
|
+
* Arr.head([]); // None
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
const head: <A>(data: readonly A[]) => Option<A>;
|
|
30
|
+
/**
|
|
31
|
+
* Returns the last element of an array, or None if the array is empty.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```ts
|
|
35
|
+
* Arr.last([1, 2, 3]); // Some(3)
|
|
36
|
+
* Arr.last([]); // None
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
const last: <A>(data: readonly A[]) => Option<A>;
|
|
40
|
+
/**
|
|
41
|
+
* Returns all elements except the first, or None if the array is empty.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* Arr.tail([1, 2, 3]); // Some([2, 3])
|
|
46
|
+
* Arr.tail([]); // None
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
const tail: <A>(data: readonly A[]) => Option<readonly A[]>;
|
|
50
|
+
/**
|
|
51
|
+
* Returns all elements except the last, or None if the array is empty.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* Arr.init([1, 2, 3]); // Some([1, 2])
|
|
56
|
+
* Arr.init([]); // None
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
const init: <A>(data: readonly A[]) => Option<readonly A[]>;
|
|
60
|
+
/**
|
|
61
|
+
* Returns the first element matching the predicate, or None.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* pipe([1, 2, 3, 4], Arr.findFirst(n => n > 2)); // Some(3)
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
const findFirst: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Option<A>;
|
|
69
|
+
/**
|
|
70
|
+
* Returns the last element matching the predicate, or None.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```ts
|
|
74
|
+
* pipe([1, 2, 3, 4], Arr.findLast(n => n > 2)); // Some(4)
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
const findLast: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Option<A>;
|
|
78
|
+
/**
|
|
79
|
+
* Returns the index of the first element matching the predicate, or None.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* pipe([1, 2, 3, 4], Arr.findIndex(n => n > 2)); // Some(2)
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
const findIndex: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => Option<number>;
|
|
87
|
+
/**
|
|
88
|
+
* Transforms each element of an array.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* pipe([1, 2, 3], Arr.map(n => n * 2)); // [2, 4, 6]
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
const map: <A, B>(f: (a: A) => B) => (data: readonly A[]) => readonly B[];
|
|
96
|
+
/**
|
|
97
|
+
* Filters elements that satisfy the predicate.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* ```ts
|
|
101
|
+
* pipe([1, 2, 3, 4], Arr.filter(n => n % 2 === 0)); // [2, 4]
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
const filter: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
|
|
105
|
+
/**
|
|
106
|
+
* Splits an array into two groups based on a predicate.
|
|
107
|
+
* First group contains elements that satisfy the predicate,
|
|
108
|
+
* second group contains the rest.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* pipe([1, 2, 3, 4], Arr.partition(n => n % 2 === 0)); // [[2, 4], [1, 3]]
|
|
113
|
+
* ```
|
|
114
|
+
*/
|
|
115
|
+
const partition: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly [readonly A[], readonly A[]];
|
|
116
|
+
/**
|
|
117
|
+
* Groups elements by a key function.
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* ```ts
|
|
121
|
+
* pipe(
|
|
122
|
+
* ["apple", "avocado", "banana"],
|
|
123
|
+
* Arr.groupBy(s => s[0])
|
|
124
|
+
* ); // { a: ["apple", "avocado"], b: ["banana"] }
|
|
125
|
+
* ```
|
|
126
|
+
*/
|
|
127
|
+
const groupBy: <A>(f: (a: A) => string) => (data: readonly A[]) => Record<string, NonEmptyList<A>>;
|
|
128
|
+
/**
|
|
129
|
+
* Removes duplicate elements using strict equality.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```ts
|
|
133
|
+
* Arr.uniq([1, 2, 2, 3, 1]); // [1, 2, 3]
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
const uniq: <A>(data: readonly A[]) => readonly A[];
|
|
137
|
+
/**
|
|
138
|
+
* Removes duplicate elements by comparing the result of a key function.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* pipe(
|
|
143
|
+
* [{id: 1, name: "a"}, {id: 1, name: "b"}, {id: 2, name: "c"}],
|
|
144
|
+
* Arr.uniqBy(x => x.id)
|
|
145
|
+
* ); // [{id: 1, name: "a"}, {id: 2, name: "c"}]
|
|
146
|
+
* ```
|
|
147
|
+
*/
|
|
148
|
+
const uniqBy: <A, B>(f: (a: A) => B) => (data: readonly A[]) => readonly A[];
|
|
149
|
+
/**
|
|
150
|
+
* Sorts an array using a comparison function. Returns a new array.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```ts
|
|
154
|
+
* pipe([3, 1, 2], Arr.sortBy((a, b) => a - b)); // [1, 2, 3]
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
const sortBy: <A>(compare: (a: A, b: A) => number) => (data: readonly A[]) => readonly A[];
|
|
158
|
+
/**
|
|
159
|
+
* Pairs up elements from two arrays. Stops at the shorter array.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* pipe([1, 2, 3], Arr.zip(["a", "b"])); // [[1, "a"], [2, "b"]]
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
const zip: <B>(other: readonly B[]) => <A>(data: readonly A[]) => readonly (readonly [A, B])[];
|
|
167
|
+
/**
|
|
168
|
+
* Combines elements from two arrays using a function. Stops at the shorter array.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* ```ts
|
|
172
|
+
* pipe([1, 2], Arr.zipWith((a, b) => a + b, ["a", "b"])); // ["1a", "2b"]
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
const zipWith: <A, B, C>(f: (a: A, b: B) => C) => (other: readonly B[]) => (data: readonly A[]) => readonly C[];
|
|
176
|
+
/**
|
|
177
|
+
* Inserts a separator between every element.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* pipe([1, 2, 3], Arr.intersperse(0)); // [1, 0, 2, 0, 3]
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
const intersperse: <A>(sep: A) => (data: readonly A[]) => readonly A[];
|
|
185
|
+
/**
|
|
186
|
+
* Splits an array into chunks of the given size.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```ts
|
|
190
|
+
* pipe([1, 2, 3, 4, 5], Arr.chunksOf(2)); // [[1, 2], [3, 4], [5]]
|
|
191
|
+
* ```
|
|
192
|
+
*/
|
|
193
|
+
const chunksOf: (n: number) => <A>(data: readonly A[]) => readonly (readonly A[])[];
|
|
194
|
+
/**
|
|
195
|
+
* Flattens a nested array by one level.
|
|
196
|
+
*
|
|
197
|
+
* @example
|
|
198
|
+
* ```ts
|
|
199
|
+
* Arr.flatten([[1, 2], [3], [4, 5]]); // [1, 2, 3, 4, 5]
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
const flatten: <A>(data: readonly (readonly A[])[]) => readonly A[];
|
|
203
|
+
/**
|
|
204
|
+
* Maps each element to an array and flattens the result.
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* ```ts
|
|
208
|
+
* pipe([1, 2, 3], Arr.flatMap(n => [n, n * 10])); // [1, 10, 2, 20, 3, 30]
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
const flatMap: <A, B>(f: (a: A) => readonly B[]) => (data: readonly A[]) => readonly B[];
|
|
212
|
+
/**
|
|
213
|
+
* Reduces an array from the left.
|
|
214
|
+
*
|
|
215
|
+
* @example
|
|
216
|
+
* ```ts
|
|
217
|
+
* pipe([1, 2, 3], Arr.reduce(0, (acc, n) => acc + n)); // 6
|
|
218
|
+
* ```
|
|
219
|
+
*/
|
|
220
|
+
const reduce: <A, B>(initial: B, f: (acc: B, a: A) => B) => (data: readonly A[]) => B;
|
|
221
|
+
/**
|
|
222
|
+
* Maps each element to an Option and collects the results.
|
|
223
|
+
* Returns None if any mapping returns None.
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* ```ts
|
|
227
|
+
* const parseNum = (s: string): Option<number> => {
|
|
228
|
+
* const n = Number(s);
|
|
229
|
+
* return isNaN(n) ? Option.none() : Option.some(n);
|
|
230
|
+
* };
|
|
231
|
+
*
|
|
232
|
+
* pipe(["1", "2", "3"], Arr.traverse(parseNum)); // Some([1, 2, 3])
|
|
233
|
+
* pipe(["1", "x", "3"], Arr.traverse(parseNum)); // None
|
|
234
|
+
* ```
|
|
235
|
+
*/
|
|
236
|
+
const traverse: <A, B>(f: (a: A) => Option<B>) => (data: readonly A[]) => Option<readonly B[]>;
|
|
237
|
+
/**
|
|
238
|
+
* Maps each element to a Result and collects the results.
|
|
239
|
+
* Returns the first Err if any mapping fails.
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* ```ts
|
|
243
|
+
* pipe(
|
|
244
|
+
* [1, 2, 3],
|
|
245
|
+
* Arr.traverseResult(n => n > 0 ? Result.ok(n) : Result.err("negative"))
|
|
246
|
+
* ); // Ok([1, 2, 3])
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
const traverseResult: <E, A, B>(f: (a: A) => Result<E, B>) => (data: readonly A[]) => Result<E, readonly B[]>;
|
|
250
|
+
/**
|
|
251
|
+
* Maps each element to a Task and runs all in parallel.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```ts
|
|
255
|
+
* pipe(
|
|
256
|
+
* [1, 2, 3],
|
|
257
|
+
* Arr.traverseTask(n => Task.resolve(n * 2))
|
|
258
|
+
* )(); // Promise<[2, 4, 6]>
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
const traverseTask: <A, B>(f: (a: A) => Task<B>) => (data: readonly A[]) => Task<readonly B[]>;
|
|
262
|
+
/**
|
|
263
|
+
* Collects an array of Options into an Option of array.
|
|
264
|
+
* Returns None if any element is None.
|
|
265
|
+
*
|
|
266
|
+
* @example
|
|
267
|
+
* ```ts
|
|
268
|
+
* Arr.sequence([Option.some(1), Option.some(2)]); // Some([1, 2])
|
|
269
|
+
* Arr.sequence([Option.some(1), Option.none()]); // None
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
const sequence: <A>(data: readonly Option<A>[]) => Option<readonly A[]>;
|
|
273
|
+
/**
|
|
274
|
+
* Collects an array of Results into a Result of array.
|
|
275
|
+
* Returns the first Err if any element is Err.
|
|
276
|
+
*/
|
|
277
|
+
const sequenceResult: <E, A>(data: readonly Result<E, A>[]) => Result<E, readonly A[]>;
|
|
278
|
+
/**
|
|
279
|
+
* Collects an array of Tasks into a Task of array. Runs in parallel.
|
|
280
|
+
*/
|
|
281
|
+
const sequenceTask: <A>(data: readonly Task<A>[]) => Task<readonly A[]>;
|
|
282
|
+
/**
|
|
283
|
+
* Maps each element to a TaskResult and runs them sequentially.
|
|
284
|
+
* Returns the first Err encountered, or Ok of all results if all succeed.
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```ts
|
|
288
|
+
* const validate = (n: number): TaskResult<string, number> =>
|
|
289
|
+
* n > 0 ? TaskResult.ok(n) : TaskResult.err("non-positive");
|
|
290
|
+
*
|
|
291
|
+
* pipe(
|
|
292
|
+
* [1, 2, 3],
|
|
293
|
+
* Arr.traverseTaskResult(validate)
|
|
294
|
+
* )(); // Deferred<Ok([1, 2, 3])>
|
|
295
|
+
*
|
|
296
|
+
* pipe(
|
|
297
|
+
* [1, -1, 3],
|
|
298
|
+
* Arr.traverseTaskResult(validate)
|
|
299
|
+
* )(); // Deferred<Err("non-positive")>
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
const traverseTaskResult: <E, A, B>(f: (a: A) => Task<Result<E, B>>) => (data: readonly A[]) => Task<Result<E, readonly B[]>>;
|
|
303
|
+
/**
|
|
304
|
+
* Collects an array of TaskResults into a TaskResult of array.
|
|
305
|
+
* Returns the first Err if any element is Err, runs sequentially.
|
|
306
|
+
*/
|
|
307
|
+
const sequenceTaskResult: <E, A>(data: readonly Task<Result<E, A>>[]) => Task<Result<E, readonly A[]>>;
|
|
308
|
+
/**
|
|
309
|
+
* Returns true if the array is non-empty (type guard).
|
|
310
|
+
*/
|
|
311
|
+
const isNonEmpty: <A>(data: readonly A[]) => data is NonEmptyList<A>;
|
|
312
|
+
/**
|
|
313
|
+
* Returns the length of an array.
|
|
314
|
+
*/
|
|
315
|
+
const size: <A>(data: readonly A[]) => number;
|
|
316
|
+
/**
|
|
317
|
+
* Returns true if any element satisfies the predicate.
|
|
318
|
+
*
|
|
319
|
+
* @example
|
|
320
|
+
* ```ts
|
|
321
|
+
* pipe([1, 2, 3], Arr.some(n => n > 2)); // true
|
|
322
|
+
* ```
|
|
323
|
+
*/
|
|
324
|
+
const some: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => boolean;
|
|
325
|
+
/**
|
|
326
|
+
* Returns true if all elements satisfy the predicate.
|
|
327
|
+
*
|
|
328
|
+
* @example
|
|
329
|
+
* ```ts
|
|
330
|
+
* pipe([1, 2, 3], Arr.every(n => n > 0)); // true
|
|
331
|
+
* ```
|
|
332
|
+
*/
|
|
333
|
+
const every: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => boolean;
|
|
334
|
+
/**
|
|
335
|
+
* Reverses an array. Returns a new array.
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* ```ts
|
|
339
|
+
* Arr.reverse([1, 2, 3]); // [3, 2, 1]
|
|
340
|
+
* ```
|
|
341
|
+
*/
|
|
342
|
+
const reverse: <A>(data: readonly A[]) => readonly A[];
|
|
343
|
+
/**
|
|
344
|
+
* Takes the first n elements from an array.
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* ```ts
|
|
348
|
+
* pipe([1, 2, 3, 4], Arr.take(2)); // [1, 2]
|
|
349
|
+
* ```
|
|
350
|
+
*/
|
|
351
|
+
const take: (n: number) => <A>(data: readonly A[]) => readonly A[];
|
|
352
|
+
/**
|
|
353
|
+
* Drops the first n elements from an array.
|
|
354
|
+
*
|
|
355
|
+
* @example
|
|
356
|
+
* ```ts
|
|
357
|
+
* pipe([1, 2, 3, 4], Arr.drop(2)); // [3, 4]
|
|
358
|
+
* ```
|
|
359
|
+
*/
|
|
360
|
+
const drop: (n: number) => <A>(data: readonly A[]) => readonly A[];
|
|
361
|
+
/**
|
|
362
|
+
* Takes elements from the start while the predicate holds.
|
|
363
|
+
*
|
|
364
|
+
* @example
|
|
365
|
+
* ```ts
|
|
366
|
+
* pipe([1, 2, 3, 1], Arr.takeWhile(n => n < 3)); // [1, 2]
|
|
367
|
+
* ```
|
|
368
|
+
*/
|
|
369
|
+
const takeWhile: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
|
|
370
|
+
/**
|
|
371
|
+
* Drops elements from the start while the predicate holds.
|
|
372
|
+
*
|
|
373
|
+
* @example
|
|
374
|
+
* ```ts
|
|
375
|
+
* pipe([1, 2, 3, 1], Arr.dropWhile(n => n < 3)); // [3, 1]
|
|
376
|
+
* ```
|
|
377
|
+
*/
|
|
378
|
+
const dropWhile: <A>(predicate: (a: A) => boolean) => (data: readonly A[]) => readonly A[];
|
|
379
|
+
/**
|
|
380
|
+
* Like `reduce`, but returns every intermediate accumulator as an array.
|
|
381
|
+
* The initial value is not included — the output has the same length as the input.
|
|
382
|
+
*
|
|
383
|
+
* @example
|
|
384
|
+
* ```ts
|
|
385
|
+
* pipe([1, 2, 3], Arr.scan(0, (acc, n) => acc + n)); // [1, 3, 6]
|
|
386
|
+
* ```
|
|
387
|
+
*/
|
|
388
|
+
const scan: <A, B>(initial: B, f: (acc: B, a: A) => B) => (data: readonly A[]) => readonly B[];
|
|
389
|
+
/**
|
|
390
|
+
* Splits an array at an index into a `[before, after]` tuple.
|
|
391
|
+
* Negative indices clamp to 0; indices beyond the array length clamp to the end.
|
|
392
|
+
*
|
|
393
|
+
* @example
|
|
394
|
+
* ```ts
|
|
395
|
+
* pipe([1, 2, 3, 4], Arr.splitAt(2)); // [[1, 2], [3, 4]]
|
|
396
|
+
* pipe([1, 2, 3], Arr.splitAt(0)); // [[], [1, 2, 3]]
|
|
397
|
+
* pipe([1, 2, 3], Arr.splitAt(10)); // [[1, 2, 3], []]
|
|
398
|
+
* ```
|
|
399
|
+
*/
|
|
400
|
+
const splitAt: (index: number) => <A>(data: readonly A[]) => readonly [readonly A[], readonly A[]];
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Functional utilities for key-value dictionaries (`ReadonlyMap<K, V>`). All functions are pure
|
|
405
|
+
* and data-last — they compose naturally with `pipe`.
|
|
406
|
+
*
|
|
407
|
+
* Unlike plain objects (`Rec`), dictionaries support any key type, preserve insertion order, and
|
|
408
|
+
* make membership checks explicit via `lookup` returning `Option`.
|
|
409
|
+
*
|
|
410
|
+
* @example
|
|
411
|
+
* ```ts
|
|
412
|
+
* import { Dict } from "@nlozgachev/pipelined/utils";
|
|
413
|
+
* import { pipe } from "@nlozgachev/pipelined/composition";
|
|
414
|
+
*
|
|
415
|
+
* const scores = pipe(
|
|
416
|
+
* Dict.fromEntries([["alice", 10], ["bob", 8], ["carol", 10]] as const),
|
|
417
|
+
* Dict.filter(n => n >= 10),
|
|
418
|
+
* Dict.map(n => `${n} points`),
|
|
419
|
+
* );
|
|
420
|
+
* // ReadonlyMap { "alice" => "10 points", "carol" => "10 points" }
|
|
421
|
+
* ```
|
|
422
|
+
*/
|
|
423
|
+
declare namespace Dict {
|
|
424
|
+
/**
|
|
425
|
+
* Creates an empty dictionary.
|
|
426
|
+
*
|
|
427
|
+
* @example
|
|
428
|
+
* ```ts
|
|
429
|
+
* Dict.empty<string, number>(); // ReadonlyMap {}
|
|
430
|
+
* ```
|
|
431
|
+
*/
|
|
432
|
+
const empty: <K, V>() => ReadonlyMap<K, V>;
|
|
433
|
+
/**
|
|
434
|
+
* Creates a dictionary with a single entry.
|
|
435
|
+
*
|
|
436
|
+
* @example
|
|
437
|
+
* ```ts
|
|
438
|
+
* Dict.singleton("name", "Alice"); // ReadonlyMap { "name" => "Alice" }
|
|
439
|
+
* ```
|
|
440
|
+
*/
|
|
441
|
+
const singleton: <K, V>(key: K, value: V) => ReadonlyMap<K, V>;
|
|
442
|
+
/**
|
|
443
|
+
* Creates a dictionary from an array of key-value pairs.
|
|
444
|
+
*
|
|
445
|
+
* @example
|
|
446
|
+
* ```ts
|
|
447
|
+
* Dict.fromEntries([["a", 1], ["b", 2]]); // ReadonlyMap { "a" => 1, "b" => 2 }
|
|
448
|
+
* ```
|
|
449
|
+
*/
|
|
450
|
+
const fromEntries: <K, V>(entries: readonly (readonly [K, V])[]) => ReadonlyMap<K, V>;
|
|
451
|
+
/**
|
|
452
|
+
* Creates a dictionary from a plain object. Keys are always strings.
|
|
453
|
+
*
|
|
454
|
+
* @example
|
|
455
|
+
* ```ts
|
|
456
|
+
* Dict.fromRecord({ a: 1, b: 2 }); // ReadonlyMap { "a" => 1, "b" => 2 }
|
|
457
|
+
* ```
|
|
458
|
+
*/
|
|
459
|
+
const fromRecord: <V>(rec: Readonly<Record<string, V>>) => ReadonlyMap<string, V>;
|
|
460
|
+
/**
|
|
461
|
+
* Groups elements of an array into a dictionary keyed by the result of `keyFn`. Each key maps
|
|
462
|
+
* to the array of elements that produced it, in insertion order. Uses the native `Map.groupBy`
|
|
463
|
+
* when available, falling back to a manual loop in older environments.
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* ```ts
|
|
467
|
+
* pipe(
|
|
468
|
+
* [{ name: "alice", role: "admin" }, { name: "bob", role: "viewer" }, { name: "carol", role: "admin" }],
|
|
469
|
+
* Dict.groupBy(user => user.role),
|
|
470
|
+
* );
|
|
471
|
+
* // ReadonlyMap { "admin" => [alice, carol], "viewer" => [bob] }
|
|
472
|
+
* ```
|
|
473
|
+
*/
|
|
474
|
+
const groupBy: <K, A>(keyFn: (a: A) => K) => (items: readonly A[]) => ReadonlyMap<K, readonly A[]>;
|
|
475
|
+
/**
|
|
476
|
+
* Returns `true` if the dictionary contains the given key.
|
|
477
|
+
*
|
|
478
|
+
* @example
|
|
479
|
+
* ```ts
|
|
480
|
+
* pipe(Dict.fromEntries([["a", 1]]), Dict.has("a")); // true
|
|
481
|
+
* pipe(Dict.fromEntries([["a", 1]]), Dict.has("b")); // false
|
|
482
|
+
* ```
|
|
483
|
+
*/
|
|
484
|
+
const has: <K>(key: K) => <V>(m: ReadonlyMap<K, V>) => boolean;
|
|
485
|
+
/**
|
|
486
|
+
* Looks up a value by key, returning `Some(value)` if found and `None` if not.
|
|
487
|
+
*
|
|
488
|
+
* @example
|
|
489
|
+
* ```ts
|
|
490
|
+
* pipe(Dict.fromEntries([["a", 1]]), Dict.lookup("a")); // Some(1)
|
|
491
|
+
* pipe(Dict.fromEntries([["a", 1]]), Dict.lookup("b")); // None
|
|
492
|
+
* ```
|
|
493
|
+
*/
|
|
494
|
+
const lookup: <K>(key: K) => <V>(m: ReadonlyMap<K, V>) => Option<V>;
|
|
495
|
+
/**
|
|
496
|
+
* Returns the number of entries in the dictionary.
|
|
497
|
+
*
|
|
498
|
+
* @example
|
|
499
|
+
* ```ts
|
|
500
|
+
* Dict.size(Dict.fromEntries([["a", 1], ["b", 2]])); // 2
|
|
501
|
+
* ```
|
|
502
|
+
*/
|
|
503
|
+
const size: <K, V>(m: ReadonlyMap<K, V>) => number;
|
|
504
|
+
/**
|
|
505
|
+
* Returns `true` if the dictionary has no entries.
|
|
506
|
+
*
|
|
507
|
+
* @example
|
|
508
|
+
* ```ts
|
|
509
|
+
* Dict.isEmpty(Dict.empty()); // true
|
|
510
|
+
* ```
|
|
511
|
+
*/
|
|
512
|
+
const isEmpty: <K, V>(m: ReadonlyMap<K, V>) => boolean;
|
|
513
|
+
/**
|
|
514
|
+
* Returns all keys as a readonly array, in insertion order.
|
|
515
|
+
*
|
|
516
|
+
* @example
|
|
517
|
+
* ```ts
|
|
518
|
+
* Dict.keys(Dict.fromEntries([["a", 1], ["b", 2]])); // ["a", "b"]
|
|
519
|
+
* ```
|
|
520
|
+
*/
|
|
521
|
+
const keys: <K, V>(m: ReadonlyMap<K, V>) => readonly K[];
|
|
522
|
+
/**
|
|
523
|
+
* Returns all values as a readonly array, in insertion order.
|
|
524
|
+
*
|
|
525
|
+
* @example
|
|
526
|
+
* ```ts
|
|
527
|
+
* Dict.values(Dict.fromEntries([["a", 1], ["b", 2]])); // [1, 2]
|
|
528
|
+
* ```
|
|
529
|
+
*/
|
|
530
|
+
const values: <K, V>(m: ReadonlyMap<K, V>) => readonly V[];
|
|
531
|
+
/**
|
|
532
|
+
* Returns all key-value pairs as a readonly array of tuples, in insertion order.
|
|
533
|
+
*
|
|
534
|
+
* @example
|
|
535
|
+
* ```ts
|
|
536
|
+
* Dict.entries(Dict.fromEntries([["a", 1], ["b", 2]])); // [["a", 1], ["b", 2]]
|
|
537
|
+
* ```
|
|
538
|
+
*/
|
|
539
|
+
const entries: <K, V>(m: ReadonlyMap<K, V>) => readonly (readonly [K, V])[];
|
|
540
|
+
/**
|
|
541
|
+
* Returns a new dictionary with the given key set to the given value.
|
|
542
|
+
* If the key already exists, its value is replaced.
|
|
543
|
+
*
|
|
544
|
+
* @example
|
|
545
|
+
* ```ts
|
|
546
|
+
* pipe(Dict.fromEntries([["a", 1]]), Dict.insert("b", 2));
|
|
547
|
+
* // ReadonlyMap { "a" => 1, "b" => 2 }
|
|
548
|
+
* ```
|
|
549
|
+
*/
|
|
550
|
+
const insert: <K, V>(key: K, value: V) => (m: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
|
|
551
|
+
/**
|
|
552
|
+
* Returns a new dictionary with the given key removed.
|
|
553
|
+
* If the key does not exist, the dictionary is returned unchanged.
|
|
554
|
+
*
|
|
555
|
+
* @example
|
|
556
|
+
* ```ts
|
|
557
|
+
* pipe(Dict.fromEntries([["a", 1], ["b", 2]]), Dict.remove("a"));
|
|
558
|
+
* // ReadonlyMap { "b" => 2 }
|
|
559
|
+
* ```
|
|
560
|
+
*/
|
|
561
|
+
const remove: <K, V>(key: K) => (m: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
|
|
562
|
+
/**
|
|
563
|
+
* Returns a new dictionary with the value at `key` set by `f`. If the key does not exist,
|
|
564
|
+
* `f` receives `None`. If the key exists, `f` receives `Some(currentValue)`.
|
|
565
|
+
*
|
|
566
|
+
* Useful for incrementing counters, initialising defaults, or conditional updates.
|
|
567
|
+
*
|
|
568
|
+
* @example
|
|
569
|
+
* ```ts
|
|
570
|
+
* import { Option } from "@nlozgachev/pipelined/core";
|
|
571
|
+
*
|
|
572
|
+
* const increment = (opt: Option<number>) => Option.getOrElse(() => 0)(opt) + 1;
|
|
573
|
+
* pipe(Dict.fromEntries([["views", 5]]), Dict.upsert("views", increment)); // { views: 6 }
|
|
574
|
+
* pipe(Dict.fromEntries([["views", 5]]), Dict.upsert("likes", increment)); // { views: 5, likes: 1 }
|
|
575
|
+
* ```
|
|
576
|
+
*/
|
|
577
|
+
const upsert: <K, V>(key: K, f: (existing: Option<V>) => V) => (m: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
|
|
578
|
+
/**
|
|
579
|
+
* Transforms each value in the dictionary.
|
|
580
|
+
*
|
|
581
|
+
* @example
|
|
582
|
+
* ```ts
|
|
583
|
+
* pipe(Dict.fromEntries([["a", 1], ["b", 2]]), Dict.map(n => n * 2));
|
|
584
|
+
* // ReadonlyMap { "a" => 2, "b" => 4 }
|
|
585
|
+
* ```
|
|
586
|
+
*/
|
|
587
|
+
const map: <A, B>(f: (a: A) => B) => <K>(m: ReadonlyMap<K, A>) => ReadonlyMap<K, B>;
|
|
588
|
+
/**
|
|
589
|
+
* Transforms each value in the dictionary, also receiving the key.
|
|
590
|
+
*
|
|
591
|
+
* @example
|
|
592
|
+
* ```ts
|
|
593
|
+
* pipe(Dict.fromEntries([["a", 1], ["b", 2]]), Dict.mapWithKey((k, v) => `${k}:${v}`));
|
|
594
|
+
* // ReadonlyMap { "a" => "a:1", "b" => "b:2" }
|
|
595
|
+
* ```
|
|
596
|
+
*/
|
|
597
|
+
const mapWithKey: <K, A, B>(f: (key: K, a: A) => B) => (m: ReadonlyMap<K, A>) => ReadonlyMap<K, B>;
|
|
598
|
+
/**
|
|
599
|
+
* Returns a new dictionary containing only the entries for which the predicate returns `true`.
|
|
600
|
+
*
|
|
601
|
+
* @example
|
|
602
|
+
* ```ts
|
|
603
|
+
* pipe(Dict.fromEntries([["a", 1], ["b", 3], ["c", 0]]), Dict.filter(n => n > 0));
|
|
604
|
+
* // ReadonlyMap { "a" => 1, "b" => 3 }
|
|
605
|
+
* ```
|
|
606
|
+
*/
|
|
607
|
+
const filter: <A>(predicate: (a: A) => boolean) => <K>(m: ReadonlyMap<K, A>) => ReadonlyMap<K, A>;
|
|
608
|
+
/**
|
|
609
|
+
* Returns a new dictionary containing only the entries for which the predicate returns `true`.
|
|
610
|
+
* The predicate also receives the key.
|
|
611
|
+
*
|
|
612
|
+
* @example
|
|
613
|
+
* ```ts
|
|
614
|
+
* pipe(Dict.fromEntries([["a", 1], ["b", 2]]), Dict.filterWithKey((k, v) => k !== "a" && v > 0));
|
|
615
|
+
* // ReadonlyMap { "b" => 2 }
|
|
616
|
+
* ```
|
|
617
|
+
*/
|
|
618
|
+
const filterWithKey: <K, A>(predicate: (key: K, a: A) => boolean) => (m: ReadonlyMap<K, A>) => ReadonlyMap<K, A>;
|
|
619
|
+
/**
|
|
620
|
+
* Removes all `None` values from a `ReadonlyMap<K, Option<A>>`, returning a plain
|
|
621
|
+
* `ReadonlyMap<K, A>`. Useful when building dictionaries from fallible lookups.
|
|
622
|
+
*
|
|
623
|
+
* @example
|
|
624
|
+
* ```ts
|
|
625
|
+
* import { Option } from "@nlozgachev/pipelined/core";
|
|
626
|
+
*
|
|
627
|
+
* Dict.compact(Dict.fromEntries([
|
|
628
|
+
* ["a", Option.some(1)],
|
|
629
|
+
* ["b", Option.none()],
|
|
630
|
+
* ["c", Option.some(3)],
|
|
631
|
+
* ]));
|
|
632
|
+
* // ReadonlyMap { "a" => 1, "c" => 3 }
|
|
633
|
+
* ```
|
|
634
|
+
*/
|
|
635
|
+
const compact: <K, A>(m: ReadonlyMap<K, Option<A>>) => ReadonlyMap<K, A>;
|
|
636
|
+
/**
|
|
637
|
+
* Merges two dictionaries. When both contain the same key, the value from `other` takes
|
|
638
|
+
* precedence.
|
|
639
|
+
*
|
|
640
|
+
* @example
|
|
641
|
+
* ```ts
|
|
642
|
+
* pipe(
|
|
643
|
+
* Dict.fromEntries([["a", 1], ["b", 2]]),
|
|
644
|
+
* Dict.union(Dict.fromEntries([["b", 3], ["c", 4]])),
|
|
645
|
+
* );
|
|
646
|
+
* // ReadonlyMap { "a" => 1, "b" => 3, "c" => 4 }
|
|
647
|
+
* ```
|
|
648
|
+
*/
|
|
649
|
+
const union: <K, V>(other: ReadonlyMap<K, V>) => (m: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
|
|
650
|
+
/**
|
|
651
|
+
* Returns a new dictionary containing only the entries whose keys appear in both dictionaries.
|
|
652
|
+
* Values are taken from the left (base) dictionary.
|
|
653
|
+
*
|
|
654
|
+
* @example
|
|
655
|
+
* ```ts
|
|
656
|
+
* pipe(
|
|
657
|
+
* Dict.fromEntries([["a", 1], ["b", 2], ["c", 3]]),
|
|
658
|
+
* Dict.intersection(Dict.fromEntries([["b", 99], ["c", 0]])),
|
|
659
|
+
* );
|
|
660
|
+
* // ReadonlyMap { "b" => 2, "c" => 3 }
|
|
661
|
+
* ```
|
|
662
|
+
*/
|
|
663
|
+
const intersection: <K, V>(other: ReadonlyMap<K, unknown>) => (m: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
|
|
664
|
+
/**
|
|
665
|
+
* Returns a new dictionary containing only the entries whose keys do not appear in `other`.
|
|
666
|
+
*
|
|
667
|
+
* @example
|
|
668
|
+
* ```ts
|
|
669
|
+
* pipe(
|
|
670
|
+
* Dict.fromEntries([["a", 1], ["b", 2], ["c", 3]]),
|
|
671
|
+
* Dict.difference(Dict.fromEntries([["b", 0]])),
|
|
672
|
+
* );
|
|
673
|
+
* // ReadonlyMap { "a" => 1, "c" => 3 }
|
|
674
|
+
* ```
|
|
675
|
+
*/
|
|
676
|
+
const difference: <K, V>(other: ReadonlyMap<K, unknown>) => (m: ReadonlyMap<K, V>) => ReadonlyMap<K, V>;
|
|
677
|
+
/**
|
|
678
|
+
* Folds the dictionary into a single value by applying `f` to each value in insertion order.
|
|
679
|
+
* When you also need the key, use `reduceWithKey`.
|
|
680
|
+
*
|
|
681
|
+
* @example
|
|
682
|
+
* ```ts
|
|
683
|
+
* Dict.reduce(0, (acc, value) => acc + value)(
|
|
684
|
+
* Dict.fromEntries([["a", 1], ["b", 2], ["c", 3]])
|
|
685
|
+
* ); // 6
|
|
686
|
+
* ```
|
|
687
|
+
*/
|
|
688
|
+
const reduce: <A, B>(init: B, f: (acc: B, value: A) => B) => <K>(m: ReadonlyMap<K, A>) => B;
|
|
689
|
+
/**
|
|
690
|
+
* Folds the dictionary into a single value by applying `f` to each key-value pair in insertion
|
|
691
|
+
* order.
|
|
692
|
+
*
|
|
693
|
+
* @example
|
|
694
|
+
* ```ts
|
|
695
|
+
* Dict.reduceWithKey("", (acc, value, key) => acc + key + ":" + value + " ")(
|
|
696
|
+
* Dict.fromEntries([["a", 1], ["b", 2]])
|
|
697
|
+
* ); // "a:1 b:2 "
|
|
698
|
+
* ```
|
|
699
|
+
*/
|
|
700
|
+
const reduceWithKey: <K, A, B>(init: B, f: (acc: B, value: A, key: K) => B) => (m: ReadonlyMap<K, A>) => B;
|
|
701
|
+
/**
|
|
702
|
+
* Converts a `ReadonlyMap<string, V>` to a plain object. Only meaningful when keys are strings.
|
|
703
|
+
*
|
|
704
|
+
* @example
|
|
705
|
+
* ```ts
|
|
706
|
+
* Dict.toRecord(Dict.fromEntries([["a", 1], ["b", 2]])); // { a: 1, b: 2 }
|
|
707
|
+
* ```
|
|
708
|
+
*/
|
|
709
|
+
const toRecord: <V>(m: ReadonlyMap<string, V>) => Readonly<Record<string, V>>;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* Number utilities for common operations. All transformation functions are data-last
|
|
714
|
+
* and curried so they compose naturally with `pipe` and `Arr.map`.
|
|
715
|
+
*
|
|
716
|
+
* @example
|
|
717
|
+
* ```ts
|
|
718
|
+
* import { Num } from "@nlozgachev/pipelined/utils";
|
|
719
|
+
* import { pipe } from "@nlozgachev/pipelined/composition";
|
|
720
|
+
*
|
|
721
|
+
* pipe(
|
|
722
|
+
* Num.range(1, 6),
|
|
723
|
+
* Arr.map(Num.multiply(2)),
|
|
724
|
+
* Arr.filter(Num.between(4, 8))
|
|
725
|
+
* ); // [4, 6, 8]
|
|
726
|
+
* ```
|
|
727
|
+
*/
|
|
728
|
+
declare namespace Num {
|
|
729
|
+
/**
|
|
730
|
+
* Generates an array of numbers from `from` to `to` (both inclusive),
|
|
731
|
+
* stepping by `step` (default `1`). If `step` is negative or zero, or `from > to`,
|
|
732
|
+
* returns an empty array. When `step` does not land exactly on `to`, the last value
|
|
733
|
+
* is the largest reachable value that does not exceed `to`.
|
|
734
|
+
*
|
|
735
|
+
* @example
|
|
736
|
+
* ```ts
|
|
737
|
+
* Num.range(0, 5); // [0, 1, 2, 3, 4, 5]
|
|
738
|
+
* Num.range(0, 10, 2); // [0, 2, 4, 6, 8, 10]
|
|
739
|
+
* Num.range(0, 9, 2); // [0, 2, 4, 6, 8]
|
|
740
|
+
* Num.range(5, 0); // []
|
|
741
|
+
* Num.range(3, 3); // [3]
|
|
742
|
+
* ```
|
|
743
|
+
*/
|
|
744
|
+
const range: (from: number, to: number, step?: number) => readonly number[];
|
|
745
|
+
/**
|
|
746
|
+
* Clamps a number between `min` and `max` (both inclusive).
|
|
747
|
+
*
|
|
748
|
+
* @example
|
|
749
|
+
* ```ts
|
|
750
|
+
* pipe(150, Num.clamp(0, 100)); // 100
|
|
751
|
+
* pipe(-5, Num.clamp(0, 100)); // 0
|
|
752
|
+
* pipe(42, Num.clamp(0, 100)); // 42
|
|
753
|
+
* ```
|
|
754
|
+
*/
|
|
755
|
+
const clamp: (min: number, max: number) => (n: number) => number;
|
|
756
|
+
/**
|
|
757
|
+
* Returns `true` when the number is between `min` and `max` (both inclusive).
|
|
758
|
+
*
|
|
759
|
+
* @example
|
|
760
|
+
* ```ts
|
|
761
|
+
* pipe(5, Num.between(1, 10)); // true
|
|
762
|
+
* pipe(0, Num.between(1, 10)); // false
|
|
763
|
+
* pipe(10, Num.between(1, 10)); // true
|
|
764
|
+
* ```
|
|
765
|
+
*/
|
|
766
|
+
const between: (min: number, max: number) => (n: number) => boolean;
|
|
767
|
+
/**
|
|
768
|
+
* Parses a string as a number. Returns `None` when the result is `NaN`.
|
|
769
|
+
*
|
|
770
|
+
* @example
|
|
771
|
+
* ```ts
|
|
772
|
+
* Num.parse("42"); // Some(42)
|
|
773
|
+
* Num.parse("3.14"); // Some(3.14)
|
|
774
|
+
* Num.parse("abc"); // None
|
|
775
|
+
* Num.parse(""); // None
|
|
776
|
+
* ```
|
|
777
|
+
*/
|
|
778
|
+
const parse: (s: string) => Option<number>;
|
|
779
|
+
/**
|
|
780
|
+
* Adds `b` to a number. Data-last: use in `pipe` or `Arr.map`.
|
|
781
|
+
*
|
|
782
|
+
* @example
|
|
783
|
+
* ```ts
|
|
784
|
+
* pipe(5, Num.add(3)); // 8
|
|
785
|
+
* pipe([1, 2, 3], Arr.map(Num.add(10))); // [11, 12, 13]
|
|
786
|
+
* ```
|
|
787
|
+
*/
|
|
788
|
+
const add: (b: number) => (a: number) => number;
|
|
789
|
+
/**
|
|
790
|
+
* Subtracts `b` from a number. Data-last: `subtract(b)(a)` = `a - b`.
|
|
791
|
+
*
|
|
792
|
+
* @example
|
|
793
|
+
* ```ts
|
|
794
|
+
* pipe(10, Num.subtract(3)); // 7
|
|
795
|
+
* pipe([5, 10, 15], Arr.map(Num.subtract(2))); // [3, 8, 13]
|
|
796
|
+
* ```
|
|
797
|
+
*/
|
|
798
|
+
const subtract: (b: number) => (a: number) => number;
|
|
799
|
+
/**
|
|
800
|
+
* Multiplies a number by `b`. Data-last: use in `pipe` or `Arr.map`.
|
|
801
|
+
*
|
|
802
|
+
* @example
|
|
803
|
+
* ```ts
|
|
804
|
+
* pipe(6, Num.multiply(7)); // 42
|
|
805
|
+
* pipe([1, 2, 3], Arr.map(Num.multiply(100))); // [100, 200, 300]
|
|
806
|
+
* ```
|
|
807
|
+
*/
|
|
808
|
+
const multiply: (b: number) => (a: number) => number;
|
|
809
|
+
/**
|
|
810
|
+
* Divides a number by `b`. Data-last: `divide(b)(a)` = `a / b`.
|
|
811
|
+
*
|
|
812
|
+
* @example
|
|
813
|
+
* ```ts
|
|
814
|
+
* pipe(20, Num.divide(4)); // 5
|
|
815
|
+
* pipe([10, 20, 30], Arr.map(Num.divide(10))); // [1, 2, 3]
|
|
816
|
+
* ```
|
|
817
|
+
*/
|
|
818
|
+
const divide: (b: number) => (a: number) => number;
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
/**
|
|
822
|
+
* Functional record/object utilities that compose well with pipe.
|
|
823
|
+
* All functions are data-last and curried where applicable.
|
|
824
|
+
*
|
|
825
|
+
* @example
|
|
826
|
+
* ```ts
|
|
827
|
+
* pipe(
|
|
828
|
+
* { a: 1, b: 2, c: 3 },
|
|
829
|
+
* Rec.filter(n => n > 1),
|
|
830
|
+
* Rec.map(n => n * 10)
|
|
831
|
+
* ); // { b: 20, c: 30 }
|
|
832
|
+
* ```
|
|
833
|
+
*/
|
|
834
|
+
declare namespace Rec {
|
|
835
|
+
/**
|
|
836
|
+
* Transforms each value in a record.
|
|
837
|
+
*
|
|
838
|
+
* @example
|
|
839
|
+
* ```ts
|
|
840
|
+
* pipe({ a: 1, b: 2 }, Rec.map(n => n * 2)); // { a: 2, b: 4 }
|
|
841
|
+
* ```
|
|
842
|
+
*/
|
|
843
|
+
const map: <A, B>(f: (a: A) => B) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, B>>;
|
|
844
|
+
/**
|
|
845
|
+
* Transforms each value in a record, also receiving the key.
|
|
846
|
+
*
|
|
847
|
+
* @example
|
|
848
|
+
* ```ts
|
|
849
|
+
* pipe({ a: 1, b: 2 }, Rec.mapWithKey((k, v) => `${k}:${v}`));
|
|
850
|
+
* // { a: "a:1", b: "b:2" }
|
|
851
|
+
* ```
|
|
852
|
+
*/
|
|
853
|
+
const mapWithKey: <A, B>(f: (key: string, a: A) => B) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, B>>;
|
|
854
|
+
/**
|
|
855
|
+
* Filters values in a record by a predicate.
|
|
856
|
+
*
|
|
857
|
+
* @example
|
|
858
|
+
* ```ts
|
|
859
|
+
* pipe({ a: 1, b: 2, c: 3 }, Rec.filter(n => n > 1)); // { b: 2, c: 3 }
|
|
860
|
+
* ```
|
|
861
|
+
*/
|
|
862
|
+
const filter: <A>(predicate: (a: A) => boolean) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
|
|
863
|
+
/**
|
|
864
|
+
* Filters values in a record by a predicate that also receives the key.
|
|
865
|
+
*
|
|
866
|
+
* @example
|
|
867
|
+
* ```ts
|
|
868
|
+
* pipe({ a: 1, b: 2 }, Rec.filterWithKey((k, v) => k !== "a" && v > 0));
|
|
869
|
+
* // { b: 2 }
|
|
870
|
+
* ```
|
|
871
|
+
*/
|
|
872
|
+
const filterWithKey: <A>(predicate: (key: string, a: A) => boolean) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
|
|
873
|
+
/**
|
|
874
|
+
* Looks up a value by key, returning Option.
|
|
875
|
+
*
|
|
876
|
+
* @example
|
|
877
|
+
* ```ts
|
|
878
|
+
* pipe({ a: 1, b: 2 }, Rec.lookup("a")); // Some(1)
|
|
879
|
+
* pipe({ a: 1, b: 2 }, Rec.lookup("c")); // None
|
|
880
|
+
* ```
|
|
881
|
+
*/
|
|
882
|
+
const lookup: (key: string) => <A>(data: Readonly<Record<string, A>>) => Option<A>;
|
|
883
|
+
/**
|
|
884
|
+
* Returns all keys of a record.
|
|
885
|
+
*/
|
|
886
|
+
const keys: <A>(data: Readonly<Record<string, A>>) => readonly string[];
|
|
887
|
+
/**
|
|
888
|
+
* Returns all values of a record.
|
|
889
|
+
*/
|
|
890
|
+
const values: <A>(data: Readonly<Record<string, A>>) => readonly A[];
|
|
891
|
+
/**
|
|
892
|
+
* Returns all key-value pairs of a record.
|
|
893
|
+
*/
|
|
894
|
+
const entries: <A>(data: Readonly<Record<string, A>>) => readonly (readonly [string, A])[];
|
|
895
|
+
/**
|
|
896
|
+
* Creates a record from key-value pairs.
|
|
897
|
+
*
|
|
898
|
+
* @example
|
|
899
|
+
* ```ts
|
|
900
|
+
* Rec.fromEntries([["a", 1], ["b", 2]]); // { a: 1, b: 2 }
|
|
901
|
+
* ```
|
|
902
|
+
*/
|
|
903
|
+
const fromEntries: <A>(data: readonly (readonly [string, A])[]) => Readonly<Record<string, A>>;
|
|
904
|
+
/**
|
|
905
|
+
* Groups elements of an array into a record keyed by the result of `keyFn`. Each key maps to
|
|
906
|
+
* the array of elements that produced it, in insertion order.
|
|
907
|
+
*
|
|
908
|
+
* Unlike `Dict.groupBy`, keys are always strings. Use `Dict.groupBy` when you need non-string
|
|
909
|
+
* keys or want to avoid the plain-object prototype chain.
|
|
910
|
+
*
|
|
911
|
+
* @example
|
|
912
|
+
* ```ts
|
|
913
|
+
* pipe(
|
|
914
|
+
* ["apple", "avocado", "banana", "blueberry"],
|
|
915
|
+
* Rec.groupBy(s => s[0]),
|
|
916
|
+
* ); // { a: ["apple", "avocado"], b: ["banana", "blueberry"] }
|
|
917
|
+
* ```
|
|
918
|
+
*/
|
|
919
|
+
const groupBy: <A>(keyFn: (a: A) => string) => (items: readonly A[]) => Readonly<Record<string, readonly A[]>>;
|
|
920
|
+
/**
|
|
921
|
+
* Picks specific keys from a record.
|
|
922
|
+
*
|
|
923
|
+
* @example
|
|
924
|
+
* ```ts
|
|
925
|
+
* pipe({ a: 1, b: 2, c: 3 }, Rec.pick("a", "c")); // { a: 1, c: 3 }
|
|
926
|
+
* ```
|
|
927
|
+
*/
|
|
928
|
+
const pick: <K extends string>(...pickedKeys: K[]) => <A extends Record<K, unknown>>(data: A) => Pick<A, K>;
|
|
929
|
+
/**
|
|
930
|
+
* Omits specific keys from a record.
|
|
931
|
+
*
|
|
932
|
+
* @example
|
|
933
|
+
* ```ts
|
|
934
|
+
* pipe({ a: 1, b: 2, c: 3 }, Rec.omit("b")); // { a: 1, c: 3 }
|
|
935
|
+
* ```
|
|
936
|
+
*/
|
|
937
|
+
const omit: <K extends string>(...omittedKeys: K[]) => <A extends Record<K, unknown>>(data: A) => Omit<A, K>;
|
|
938
|
+
/**
|
|
939
|
+
* Merges two records. Values from the second record take precedence.
|
|
940
|
+
*
|
|
941
|
+
* @example
|
|
942
|
+
* ```ts
|
|
943
|
+
* pipe({ a: 1, b: 2 }, Rec.merge({ b: 3, c: 4 })); // { a: 1, b: 3, c: 4 }
|
|
944
|
+
* ```
|
|
945
|
+
*/
|
|
946
|
+
const merge: <A>(other: Readonly<Record<string, A>>) => (data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
|
|
947
|
+
/**
|
|
948
|
+
* Returns true if the record has no keys.
|
|
949
|
+
*/
|
|
950
|
+
const isEmpty: <A>(data: Readonly<Record<string, A>>) => boolean;
|
|
951
|
+
/**
|
|
952
|
+
* Returns the number of keys in a record.
|
|
953
|
+
*/
|
|
954
|
+
const size: <A>(data: Readonly<Record<string, A>>) => number;
|
|
955
|
+
/**
|
|
956
|
+
* Transforms each key while preserving values.
|
|
957
|
+
* If two keys map to the same new key, the last one wins.
|
|
958
|
+
*
|
|
959
|
+
* @example
|
|
960
|
+
* ```ts
|
|
961
|
+
* pipe({ firstName: "Alice", lastName: "Smith" }, Rec.mapKeys(k => k.toUpperCase()));
|
|
962
|
+
* // { FIRSTNAME: "Alice", LASTNAME: "Smith" }
|
|
963
|
+
* ```
|
|
964
|
+
*/
|
|
965
|
+
const mapKeys: (f: (key: string) => string) => <A>(data: Readonly<Record<string, A>>) => Readonly<Record<string, A>>;
|
|
966
|
+
/**
|
|
967
|
+
* Removes all `None` values from a `Record<string, Option<A>>`, returning a plain `Record<string, A>`.
|
|
968
|
+
* Useful when building records from fallible lookups.
|
|
969
|
+
*
|
|
970
|
+
* @example
|
|
971
|
+
* ```ts
|
|
972
|
+
* Rec.compact({ a: Option.some(1), b: Option.none(), c: Option.some(3) });
|
|
973
|
+
* // { a: 1, c: 3 }
|
|
974
|
+
* ```
|
|
975
|
+
*/
|
|
976
|
+
const compact: <A>(data: Readonly<Record<string, Option<A>>>) => Readonly<Record<string, A>>;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
/**
|
|
980
|
+
* String utilities. All transformation functions are data-last and curried so they
|
|
981
|
+
* compose naturally with `pipe`. Safe parsers return `Option` instead of `NaN`.
|
|
982
|
+
*
|
|
983
|
+
* @example
|
|
984
|
+
* ```ts
|
|
985
|
+
* import { Str } from "@nlozgachev/pipelined/utils";
|
|
986
|
+
* import { pipe } from "@nlozgachev/pipelined/composition";
|
|
987
|
+
*
|
|
988
|
+
* pipe(" Hello, World! ", Str.trim, Str.toLowerCase); // "hello, world!"
|
|
989
|
+
* ```
|
|
990
|
+
*/
|
|
991
|
+
declare namespace Str {
|
|
992
|
+
/**
|
|
993
|
+
* Splits a string by a separator. Data-last: use in `pipe`.
|
|
994
|
+
*
|
|
995
|
+
* @example
|
|
996
|
+
* ```ts
|
|
997
|
+
* pipe("a,b,c", Str.split(",")); // ["a", "b", "c"]
|
|
998
|
+
* ```
|
|
999
|
+
*/
|
|
1000
|
+
const split: (separator: string | RegExp) => (s: string) => readonly string[];
|
|
1001
|
+
/**
|
|
1002
|
+
* Removes leading and trailing whitespace from a string.
|
|
1003
|
+
*
|
|
1004
|
+
* @example
|
|
1005
|
+
* ```ts
|
|
1006
|
+
* pipe(" hello ", Str.trim); // "hello"
|
|
1007
|
+
* ```
|
|
1008
|
+
*/
|
|
1009
|
+
const trim: (s: string) => string;
|
|
1010
|
+
/**
|
|
1011
|
+
* Returns `true` when the string contains the given substring.
|
|
1012
|
+
*
|
|
1013
|
+
* @example
|
|
1014
|
+
* ```ts
|
|
1015
|
+
* pipe("hello world", Str.includes("world")); // true
|
|
1016
|
+
* pipe("hello world", Str.includes("xyz")); // false
|
|
1017
|
+
* ```
|
|
1018
|
+
*/
|
|
1019
|
+
const includes: (substring: string) => (s: string) => boolean;
|
|
1020
|
+
/**
|
|
1021
|
+
* Returns `true` when the string starts with the given prefix.
|
|
1022
|
+
*
|
|
1023
|
+
* @example
|
|
1024
|
+
* ```ts
|
|
1025
|
+
* pipe("hello world", Str.startsWith("hello")); // true
|
|
1026
|
+
* pipe("hello world", Str.startsWith("world")); // false
|
|
1027
|
+
* ```
|
|
1028
|
+
*/
|
|
1029
|
+
const startsWith: (prefix: string) => (s: string) => boolean;
|
|
1030
|
+
/**
|
|
1031
|
+
* Returns `true` when the string ends with the given suffix.
|
|
1032
|
+
*
|
|
1033
|
+
* @example
|
|
1034
|
+
* ```ts
|
|
1035
|
+
* pipe("hello world", Str.endsWith("world")); // true
|
|
1036
|
+
* pipe("hello world", Str.endsWith("hello")); // false
|
|
1037
|
+
* ```
|
|
1038
|
+
*/
|
|
1039
|
+
const endsWith: (suffix: string) => (s: string) => boolean;
|
|
1040
|
+
/**
|
|
1041
|
+
* Converts a string to uppercase.
|
|
1042
|
+
*
|
|
1043
|
+
* @example
|
|
1044
|
+
* ```ts
|
|
1045
|
+
* pipe("hello", Str.toUpperCase); // "HELLO"
|
|
1046
|
+
* ```
|
|
1047
|
+
*/
|
|
1048
|
+
const toUpperCase: (s: string) => string;
|
|
1049
|
+
/**
|
|
1050
|
+
* Converts a string to lowercase.
|
|
1051
|
+
*
|
|
1052
|
+
* @example
|
|
1053
|
+
* ```ts
|
|
1054
|
+
* pipe("HELLO", Str.toLowerCase); // "hello"
|
|
1055
|
+
* ```
|
|
1056
|
+
*/
|
|
1057
|
+
const toLowerCase: (s: string) => string;
|
|
1058
|
+
/**
|
|
1059
|
+
* Splits a string into lines, normalising `\r\n` and `\r` line endings.
|
|
1060
|
+
*
|
|
1061
|
+
* @example
|
|
1062
|
+
* ```ts
|
|
1063
|
+
* Str.lines("one\ntwo\nthree"); // ["one", "two", "three"]
|
|
1064
|
+
* Str.lines("a\r\nb"); // ["a", "b"]
|
|
1065
|
+
* ```
|
|
1066
|
+
*/
|
|
1067
|
+
const lines: (s: string) => readonly string[];
|
|
1068
|
+
/**
|
|
1069
|
+
* Splits a string into words on any whitespace boundary, filtering out empty strings.
|
|
1070
|
+
*
|
|
1071
|
+
* @example
|
|
1072
|
+
* ```ts
|
|
1073
|
+
* Str.words(" hello world "); // ["hello", "world"]
|
|
1074
|
+
* ```
|
|
1075
|
+
*/
|
|
1076
|
+
const words: (s: string) => readonly string[];
|
|
1077
|
+
/**
|
|
1078
|
+
* Safe number parsers that return `Option` instead of `NaN`.
|
|
1079
|
+
*/
|
|
1080
|
+
const parse: {
|
|
1081
|
+
/**
|
|
1082
|
+
* Parses a string as an integer (base 10). Returns `None` if the result is `NaN`.
|
|
1083
|
+
*
|
|
1084
|
+
* @example
|
|
1085
|
+
* ```ts
|
|
1086
|
+
* Str.parse.int("42"); // Some(42)
|
|
1087
|
+
* Str.parse.int("3.7"); // Some(3)
|
|
1088
|
+
* Str.parse.int("abc"); // None
|
|
1089
|
+
* ```
|
|
1090
|
+
*/
|
|
1091
|
+
int: (s: string) => Option<number>;
|
|
1092
|
+
/**
|
|
1093
|
+
* Parses a string as a floating-point number. Returns `None` if the result is `NaN`.
|
|
1094
|
+
*
|
|
1095
|
+
* @example
|
|
1096
|
+
* ```ts
|
|
1097
|
+
* Str.parse.float("3.14"); // Some(3.14)
|
|
1098
|
+
* Str.parse.float("42"); // Some(42)
|
|
1099
|
+
* Str.parse.float("abc"); // None
|
|
1100
|
+
* ```
|
|
1101
|
+
*/
|
|
1102
|
+
float: (s: string) => Option<number>;
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
/**
|
|
1107
|
+
* Functional utilities for unique-value collections (`ReadonlySet<A>`). All functions are pure
|
|
1108
|
+
* and data-last — they compose naturally with `pipe`.
|
|
1109
|
+
*
|
|
1110
|
+
* Every "mutating" operation returns a new set; the original is never changed.
|
|
1111
|
+
*
|
|
1112
|
+
* @example
|
|
1113
|
+
* ```ts
|
|
1114
|
+
* import { Uniq } from "@nlozgachev/pipelined/utils";
|
|
1115
|
+
* import { pipe } from "@nlozgachev/pipelined/composition";
|
|
1116
|
+
*
|
|
1117
|
+
* const active = pipe(
|
|
1118
|
+
* Uniq.fromArray(["alice", "bob", "alice", "carol"]),
|
|
1119
|
+
* Uniq.remove("bob"),
|
|
1120
|
+
* Uniq.map(name => name.toUpperCase()),
|
|
1121
|
+
* );
|
|
1122
|
+
* // ReadonlySet { "ALICE", "CAROL" }
|
|
1123
|
+
* ```
|
|
1124
|
+
*/
|
|
1125
|
+
declare namespace Uniq {
|
|
1126
|
+
/**
|
|
1127
|
+
* Creates an empty unique collection.
|
|
1128
|
+
*
|
|
1129
|
+
* @example
|
|
1130
|
+
* ```ts
|
|
1131
|
+
* Uniq.empty<number>(); // ReadonlySet {}
|
|
1132
|
+
* ```
|
|
1133
|
+
*/
|
|
1134
|
+
const empty: <A>() => ReadonlySet<A>;
|
|
1135
|
+
/**
|
|
1136
|
+
* Creates a unique collection containing a single item.
|
|
1137
|
+
*
|
|
1138
|
+
* @example
|
|
1139
|
+
* ```ts
|
|
1140
|
+
* Uniq.singleton(42); // ReadonlySet { 42 }
|
|
1141
|
+
* ```
|
|
1142
|
+
*/
|
|
1143
|
+
const singleton: <A>(item: A) => ReadonlySet<A>;
|
|
1144
|
+
/**
|
|
1145
|
+
* Creates a unique collection from an array, automatically discarding duplicates.
|
|
1146
|
+
*
|
|
1147
|
+
* @example
|
|
1148
|
+
* ```ts
|
|
1149
|
+
* Uniq.fromArray([1, 2, 2, 3, 3, 3]); // ReadonlySet { 1, 2, 3 }
|
|
1150
|
+
* Uniq.fromArray([]); // ReadonlySet {}
|
|
1151
|
+
* ```
|
|
1152
|
+
*/
|
|
1153
|
+
const fromArray: <A>(arr: readonly A[]) => ReadonlySet<A>;
|
|
1154
|
+
/**
|
|
1155
|
+
* Returns `true` if the collection contains the given item.
|
|
1156
|
+
*
|
|
1157
|
+
* @example
|
|
1158
|
+
* ```ts
|
|
1159
|
+
* pipe(Uniq.fromArray([1, 2, 3]), Uniq.has(2)); // true
|
|
1160
|
+
* pipe(Uniq.fromArray([1, 2, 3]), Uniq.has(4)); // false
|
|
1161
|
+
* ```
|
|
1162
|
+
*/
|
|
1163
|
+
const has: <A>(item: A) => (s: ReadonlySet<A>) => boolean;
|
|
1164
|
+
/**
|
|
1165
|
+
* Returns the number of items in the collection.
|
|
1166
|
+
*
|
|
1167
|
+
* @example
|
|
1168
|
+
* ```ts
|
|
1169
|
+
* Uniq.size(Uniq.fromArray([1, 2, 3])); // 3
|
|
1170
|
+
* ```
|
|
1171
|
+
*/
|
|
1172
|
+
const size: <A>(s: ReadonlySet<A>) => number;
|
|
1173
|
+
/**
|
|
1174
|
+
* Returns `true` if the collection has no items.
|
|
1175
|
+
*
|
|
1176
|
+
* @example
|
|
1177
|
+
* ```ts
|
|
1178
|
+
* Uniq.isEmpty(Uniq.empty()); // true
|
|
1179
|
+
* ```
|
|
1180
|
+
*/
|
|
1181
|
+
const isEmpty: <A>(s: ReadonlySet<A>) => boolean;
|
|
1182
|
+
/**
|
|
1183
|
+
* Returns `true` if every item in `set` also exists in `other`.
|
|
1184
|
+
*
|
|
1185
|
+
* @example
|
|
1186
|
+
* ```ts
|
|
1187
|
+
* pipe(Uniq.fromArray([1, 2]), Uniq.isSubsetOf(Uniq.fromArray([1, 2, 3]))); // true
|
|
1188
|
+
* pipe(Uniq.fromArray([1, 4]), Uniq.isSubsetOf(Uniq.fromArray([1, 2, 3]))); // false
|
|
1189
|
+
* pipe(Uniq.empty<number>(), Uniq.isSubsetOf(Uniq.fromArray([1, 2, 3]))); // true
|
|
1190
|
+
* ```
|
|
1191
|
+
*/
|
|
1192
|
+
const isSubsetOf: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => boolean;
|
|
1193
|
+
/**
|
|
1194
|
+
* Returns a new collection with the item added. If the item is already present, returns the
|
|
1195
|
+
* original collection unchanged.
|
|
1196
|
+
*
|
|
1197
|
+
* @example
|
|
1198
|
+
* ```ts
|
|
1199
|
+
* pipe(Uniq.fromArray([1, 2]), Uniq.insert(3)); // ReadonlySet { 1, 2, 3 }
|
|
1200
|
+
* pipe(Uniq.fromArray([1, 2]), Uniq.insert(2)); // ReadonlySet { 1, 2 } — unchanged
|
|
1201
|
+
* ```
|
|
1202
|
+
*/
|
|
1203
|
+
const insert: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
|
|
1204
|
+
/**
|
|
1205
|
+
* Returns a new collection with the item removed. If the item is not present, returns the
|
|
1206
|
+
* original collection unchanged.
|
|
1207
|
+
*
|
|
1208
|
+
* @example
|
|
1209
|
+
* ```ts
|
|
1210
|
+
* pipe(Uniq.fromArray([1, 2, 3]), Uniq.remove(2)); // ReadonlySet { 1, 3 }
|
|
1211
|
+
* pipe(Uniq.fromArray([1, 2, 3]), Uniq.remove(4)); // ReadonlySet { 1, 2, 3 } — unchanged
|
|
1212
|
+
* ```
|
|
1213
|
+
*/
|
|
1214
|
+
const remove: <A>(item: A) => (s: ReadonlySet<A>) => ReadonlySet<A>;
|
|
1215
|
+
/**
|
|
1216
|
+
* Applies `f` to each item, returning a new collection of the results. Duplicate results are
|
|
1217
|
+
* automatically merged.
|
|
1218
|
+
*
|
|
1219
|
+
* @example
|
|
1220
|
+
* ```ts
|
|
1221
|
+
* pipe(Uniq.fromArray([1, 2, 3, 4]), Uniq.map(n => n % 3)); // ReadonlySet { 1, 2, 0 }
|
|
1222
|
+
* ```
|
|
1223
|
+
*/
|
|
1224
|
+
const map: <A, B>(f: (a: A) => B) => (s: ReadonlySet<A>) => ReadonlySet<B>;
|
|
1225
|
+
/**
|
|
1226
|
+
* Returns a new collection containing only the items for which the predicate returns `true`.
|
|
1227
|
+
*
|
|
1228
|
+
* @example
|
|
1229
|
+
* ```ts
|
|
1230
|
+
* pipe(Uniq.fromArray([1, 2, 3, 4, 5]), Uniq.filter(n => n % 2 === 0));
|
|
1231
|
+
* // ReadonlySet { 2, 4 }
|
|
1232
|
+
* ```
|
|
1233
|
+
*/
|
|
1234
|
+
const filter: <A>(predicate: (a: A) => boolean) => (s: ReadonlySet<A>) => ReadonlySet<A>;
|
|
1235
|
+
/**
|
|
1236
|
+
* Returns a new collection containing all items from both collections.
|
|
1237
|
+
*
|
|
1238
|
+
* @example
|
|
1239
|
+
* ```ts
|
|
1240
|
+
* pipe(Uniq.fromArray([1, 2, 3]), Uniq.union(Uniq.fromArray([2, 3, 4])));
|
|
1241
|
+
* // ReadonlySet { 1, 2, 3, 4 }
|
|
1242
|
+
* ```
|
|
1243
|
+
*/
|
|
1244
|
+
const union: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
|
|
1245
|
+
/**
|
|
1246
|
+
* Returns a new collection containing only the items that appear in both collections.
|
|
1247
|
+
*
|
|
1248
|
+
* @example
|
|
1249
|
+
* ```ts
|
|
1250
|
+
* pipe(Uniq.fromArray([1, 2, 3]), Uniq.intersection(Uniq.fromArray([2, 3, 4])));
|
|
1251
|
+
* // ReadonlySet { 2, 3 }
|
|
1252
|
+
* ```
|
|
1253
|
+
*/
|
|
1254
|
+
const intersection: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
|
|
1255
|
+
/**
|
|
1256
|
+
* Returns a new collection containing only the items from `set` that do not appear in `other`.
|
|
1257
|
+
*
|
|
1258
|
+
* @example
|
|
1259
|
+
* ```ts
|
|
1260
|
+
* pipe(Uniq.fromArray([1, 2, 3, 4]), Uniq.difference(Uniq.fromArray([2, 4])));
|
|
1261
|
+
* // ReadonlySet { 1, 3 }
|
|
1262
|
+
* ```
|
|
1263
|
+
*/
|
|
1264
|
+
const difference: <A>(other: ReadonlySet<A>) => (s: ReadonlySet<A>) => ReadonlySet<A>;
|
|
1265
|
+
/**
|
|
1266
|
+
* Folds the collection into a single value by applying `f` to each item in insertion order.
|
|
1267
|
+
*
|
|
1268
|
+
* @example
|
|
1269
|
+
* ```ts
|
|
1270
|
+
* Uniq.reduce(0, (acc, n) => acc + n)(Uniq.fromArray([1, 2, 3])); // 6
|
|
1271
|
+
* ```
|
|
1272
|
+
*/
|
|
1273
|
+
const reduce: <A, B>(init: B, f: (acc: B, a: A) => B) => (s: ReadonlySet<A>) => B;
|
|
1274
|
+
/**
|
|
1275
|
+
* Converts the collection to a readonly array in insertion order.
|
|
1276
|
+
*
|
|
1277
|
+
* @example
|
|
1278
|
+
* ```ts
|
|
1279
|
+
* Uniq.toArray(Uniq.fromArray([3, 1, 2])); // [3, 1, 2]
|
|
1280
|
+
* ```
|
|
1281
|
+
*/
|
|
1282
|
+
const toArray: <A>(s: ReadonlySet<A>) => readonly A[];
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
export { Arr, Dict, Num, Rec, Str, Uniq };
|