@sylphx/flow 2.18.0 → 2.18.2
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/CHANGELOG.md +18 -0
- package/assets/slash-commands/continue.md +21 -63
- package/assets/slash-commands/review.md +17 -12
- package/package.json +1 -1
- package/src/core/backup-manager.ts +3 -14
- package/src/core/secrets-manager.ts +3 -14
- package/src/core/target-resolver.ts +28 -0
- package/src/utils/index.ts +1 -5
- package/src/utils/functional/array.ts +0 -355
- package/src/utils/functional/index.ts +0 -15
- package/src/utils/functional/object.ts +0 -279
- package/src/utils/functional/string.ts +0 -281
- package/src/utils/functional.ts +0 -543
package/src/utils/functional.ts
DELETED
|
@@ -1,543 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Functional Programming Utilities
|
|
3
|
-
* Core utilities for functional composition and transformation
|
|
4
|
-
*
|
|
5
|
-
* Principles:
|
|
6
|
-
* - Pure functions (no side effects)
|
|
7
|
-
* - Immutable data
|
|
8
|
-
* - Function composition
|
|
9
|
-
* - Point-free style support
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
// ============================================================================
|
|
13
|
-
// FUNCTION COMPOSITION
|
|
14
|
-
// ============================================================================
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Pipe - Left-to-right function composition
|
|
18
|
-
* Applies functions sequentially from left to right
|
|
19
|
-
*
|
|
20
|
-
* @example
|
|
21
|
-
* const result = pipe(
|
|
22
|
-
* 5,
|
|
23
|
-
* x => x * 2, // 10
|
|
24
|
-
* x => x + 3, // 13
|
|
25
|
-
* x => x.toString() // "13"
|
|
26
|
-
* );
|
|
27
|
-
*/
|
|
28
|
-
export const pipe = <T>(value: T, ...fns: Array<(arg: any) => any>): any =>
|
|
29
|
-
fns.reduce((acc, fn) => fn(acc), value);
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Compose - Right-to-left function composition
|
|
33
|
-
* Applies functions sequentially from right to left
|
|
34
|
-
*
|
|
35
|
-
* @example
|
|
36
|
-
* const addThenMultiply = compose(
|
|
37
|
-
* (x: number) => x * 2, // Applied second
|
|
38
|
-
* (x: number) => x + 3 // Applied first
|
|
39
|
-
* );
|
|
40
|
-
* addThenMultiply(5); // (5 + 3) * 2 = 16
|
|
41
|
-
*/
|
|
42
|
-
export const compose =
|
|
43
|
-
<T>(...fns: Array<(arg: any) => any>) =>
|
|
44
|
-
(value: T): any =>
|
|
45
|
-
fns.reduceRight((acc, fn) => fn(acc), value);
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Flow - Alias for pipe (for function composition without initial value)
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* const transform = flow(
|
|
52
|
-
* (x: number) => x * 2,
|
|
53
|
-
* (x: number) => x + 3,
|
|
54
|
-
* (x: number) => x.toString()
|
|
55
|
-
* );
|
|
56
|
-
* transform(5); // "13"
|
|
57
|
-
*/
|
|
58
|
-
export const flow =
|
|
59
|
-
<A, B>(...fns: Array<(arg: any) => any>) =>
|
|
60
|
-
(value: A): B =>
|
|
61
|
-
pipe(value, ...fns);
|
|
62
|
-
|
|
63
|
-
// ============================================================================
|
|
64
|
-
// CURRYING & PARTIAL APPLICATION
|
|
65
|
-
// ============================================================================
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Curry - Transform multi-argument function to curried form
|
|
69
|
-
*
|
|
70
|
-
* @example
|
|
71
|
-
* const add = (a: number, b: number) => a + b;
|
|
72
|
-
* const curriedAdd = curry(add);
|
|
73
|
-
* curriedAdd(5)(3); // 8
|
|
74
|
-
*/
|
|
75
|
-
export const curry =
|
|
76
|
-
<A, B, C>(fn: (a: A, b: B) => C) =>
|
|
77
|
-
(a: A) =>
|
|
78
|
-
(b: B): C =>
|
|
79
|
-
fn(a, b);
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Curry3 - Curry function with 3 arguments
|
|
83
|
-
*/
|
|
84
|
-
export const curry3 =
|
|
85
|
-
<A, B, C, D>(fn: (a: A, b: B, c: C) => D) =>
|
|
86
|
-
(a: A) =>
|
|
87
|
-
(b: B) =>
|
|
88
|
-
(c: C): D =>
|
|
89
|
-
fn(a, b, c);
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Partial - Partial application of function arguments
|
|
93
|
-
*
|
|
94
|
-
* @example
|
|
95
|
-
* const add = (a: number, b: number, c: number) => a + b + c;
|
|
96
|
-
* const add5 = partial(add, 5);
|
|
97
|
-
* add5(3, 2); // 10
|
|
98
|
-
*/
|
|
99
|
-
export const partial =
|
|
100
|
-
<A extends any[], R>(fn: (...args: A) => R, ...partialArgs: Partial<A>) =>
|
|
101
|
-
(...remainingArgs: any[]): R =>
|
|
102
|
-
fn(...([...partialArgs, ...remainingArgs] as A));
|
|
103
|
-
|
|
104
|
-
// ============================================================================
|
|
105
|
-
// ARRAY TRANSFORMATIONS (Point-free style)
|
|
106
|
-
// ============================================================================
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Map - Transform array elements
|
|
110
|
-
*
|
|
111
|
-
* @example
|
|
112
|
-
* pipe(
|
|
113
|
-
* [1, 2, 3],
|
|
114
|
-
* map((x: number) => x * 2)
|
|
115
|
-
* ); // [2, 4, 6]
|
|
116
|
-
*/
|
|
117
|
-
export const map =
|
|
118
|
-
<A, B>(fn: (item: A, index: number) => B) =>
|
|
119
|
-
(items: readonly A[]): B[] =>
|
|
120
|
-
items.map(fn);
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Filter - Keep elements matching predicate
|
|
124
|
-
*
|
|
125
|
-
* @example
|
|
126
|
-
* pipe(
|
|
127
|
-
* [1, 2, 3, 4],
|
|
128
|
-
* filter((x: number) => x > 2)
|
|
129
|
-
* ); // [3, 4]
|
|
130
|
-
*/
|
|
131
|
-
export const filter =
|
|
132
|
-
<A>(predicate: (item: A, index: number) => boolean) =>
|
|
133
|
-
(items: readonly A[]): A[] =>
|
|
134
|
-
items.filter(predicate);
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Reduce - Accumulate array to single value
|
|
138
|
-
*
|
|
139
|
-
* @example
|
|
140
|
-
* pipe(
|
|
141
|
-
* [1, 2, 3, 4],
|
|
142
|
-
* reduce((acc: number, x: number) => acc + x, 0)
|
|
143
|
-
* ); // 10
|
|
144
|
-
*/
|
|
145
|
-
export const reduce =
|
|
146
|
-
<A, B>(fn: (acc: B, item: A, index: number) => B, initial: B) =>
|
|
147
|
-
(items: readonly A[]): B =>
|
|
148
|
-
items.reduce(fn, initial);
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* FlatMap - Map then flatten
|
|
152
|
-
*
|
|
153
|
-
* @example
|
|
154
|
-
* pipe(
|
|
155
|
-
* [1, 2, 3],
|
|
156
|
-
* flatMap((x: number) => [x, x * 2])
|
|
157
|
-
* ); // [1, 2, 2, 4, 3, 6]
|
|
158
|
-
*/
|
|
159
|
-
export const flatMap =
|
|
160
|
-
<A, B>(fn: (item: A, index: number) => B[]) =>
|
|
161
|
-
(items: readonly A[]): B[] =>
|
|
162
|
-
items.flatMap(fn);
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Sort - Sort array (returns new array)
|
|
166
|
-
*
|
|
167
|
-
* @example
|
|
168
|
-
* pipe(
|
|
169
|
-
* [3, 1, 2],
|
|
170
|
-
* sort((a: number, b: number) => a - b)
|
|
171
|
-
* ); // [1, 2, 3]
|
|
172
|
-
*/
|
|
173
|
-
export const sort =
|
|
174
|
-
<A>(compareFn: (a: A, b: A) => number) =>
|
|
175
|
-
(items: readonly A[]): A[] =>
|
|
176
|
-
[...items].sort(compareFn);
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* SortBy - Sort by property
|
|
180
|
-
*
|
|
181
|
-
* @example
|
|
182
|
-
* pipe(
|
|
183
|
-
* [{ age: 30 }, { age: 20 }, { age: 25 }],
|
|
184
|
-
* sortBy('age')
|
|
185
|
-
* ); // [{ age: 20 }, { age: 25 }, { age: 30 }]
|
|
186
|
-
*/
|
|
187
|
-
export const sortBy =
|
|
188
|
-
<A>(key: keyof A) =>
|
|
189
|
-
(items: readonly A[]): A[] =>
|
|
190
|
-
[...items].sort((a, b) => {
|
|
191
|
-
if (a[key] < b[key]) {
|
|
192
|
-
return -1;
|
|
193
|
-
}
|
|
194
|
-
if (a[key] > b[key]) {
|
|
195
|
-
return 1;
|
|
196
|
-
}
|
|
197
|
-
return 0;
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Reverse - Reverse array (returns new array)
|
|
202
|
-
*/
|
|
203
|
-
export const reverse = <A>(items: readonly A[]): A[] => [...items].reverse();
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Take - Take first n elements
|
|
207
|
-
*
|
|
208
|
-
* @example
|
|
209
|
-
* pipe([1, 2, 3, 4, 5], take(3)); // [1, 2, 3]
|
|
210
|
-
*/
|
|
211
|
-
export const take =
|
|
212
|
-
(n: number) =>
|
|
213
|
-
<A>(items: readonly A[]): A[] =>
|
|
214
|
-
items.slice(0, n);
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Drop - Drop first n elements
|
|
218
|
-
*
|
|
219
|
-
* @example
|
|
220
|
-
* pipe([1, 2, 3, 4, 5], drop(2)); // [3, 4, 5]
|
|
221
|
-
*/
|
|
222
|
-
export const drop =
|
|
223
|
-
(n: number) =>
|
|
224
|
-
<A>(items: readonly A[]): A[] =>
|
|
225
|
-
items.slice(n);
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Unique - Remove duplicates
|
|
229
|
-
*
|
|
230
|
-
* @example
|
|
231
|
-
* pipe([1, 2, 2, 3, 3, 3], unique); // [1, 2, 3]
|
|
232
|
-
*/
|
|
233
|
-
export const unique = <A>(items: readonly A[]): A[] => [...new Set(items)];
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* UniqueBy - Remove duplicates by key
|
|
237
|
-
*
|
|
238
|
-
* @example
|
|
239
|
-
* pipe(
|
|
240
|
-
* [{ id: 1 }, { id: 2 }, { id: 1 }],
|
|
241
|
-
* uniqueBy('id')
|
|
242
|
-
* ); // [{ id: 1 }, { id: 2 }]
|
|
243
|
-
*/
|
|
244
|
-
export const uniqueBy =
|
|
245
|
-
<A>(key: keyof A) =>
|
|
246
|
-
(items: readonly A[]): A[] => {
|
|
247
|
-
const seen = new Set();
|
|
248
|
-
return items.filter((item) => {
|
|
249
|
-
const value = item[key];
|
|
250
|
-
if (seen.has(value)) {
|
|
251
|
-
return false;
|
|
252
|
-
}
|
|
253
|
-
seen.add(value);
|
|
254
|
-
return true;
|
|
255
|
-
});
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Partition - Split array by predicate
|
|
260
|
-
*
|
|
261
|
-
* @example
|
|
262
|
-
* pipe(
|
|
263
|
-
* [1, 2, 3, 4, 5],
|
|
264
|
-
* partition((x: number) => x > 3)
|
|
265
|
-
* ); // [[4, 5], [1, 2, 3]]
|
|
266
|
-
*/
|
|
267
|
-
export const partition =
|
|
268
|
-
<A>(predicate: (item: A) => boolean) =>
|
|
269
|
-
(items: readonly A[]): [A[], A[]] => {
|
|
270
|
-
const pass: A[] = [];
|
|
271
|
-
const fail: A[] = [];
|
|
272
|
-
for (const item of items) {
|
|
273
|
-
(predicate(item) ? pass : fail).push(item);
|
|
274
|
-
}
|
|
275
|
-
return [pass, fail];
|
|
276
|
-
};
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* GroupBy - Group items by key
|
|
280
|
-
*
|
|
281
|
-
* @example
|
|
282
|
-
* pipe(
|
|
283
|
-
* [{ type: 'a', val: 1 }, { type: 'b', val: 2 }, { type: 'a', val: 3 }],
|
|
284
|
-
* groupBy('type')
|
|
285
|
-
* ); // { a: [...], b: [...] }
|
|
286
|
-
*/
|
|
287
|
-
export const groupBy =
|
|
288
|
-
<A>(key: keyof A) =>
|
|
289
|
-
(items: readonly A[]): Record<string, A[]> =>
|
|
290
|
-
items.reduce(
|
|
291
|
-
(acc, item) => {
|
|
292
|
-
const groupKey = String(item[key]);
|
|
293
|
-
if (!acc[groupKey]) {
|
|
294
|
-
acc[groupKey] = [];
|
|
295
|
-
}
|
|
296
|
-
acc[groupKey].push(item);
|
|
297
|
-
return acc;
|
|
298
|
-
},
|
|
299
|
-
{} as Record<string, A[]>
|
|
300
|
-
);
|
|
301
|
-
|
|
302
|
-
// ============================================================================
|
|
303
|
-
// ASYNC TRANSFORMATIONS
|
|
304
|
-
// ============================================================================
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* MapAsync - Map with async function
|
|
308
|
-
*
|
|
309
|
-
* @example
|
|
310
|
-
* await pipe(
|
|
311
|
-
* [1, 2, 3],
|
|
312
|
-
* mapAsync(async (x) => x * 2)
|
|
313
|
-
* ); // [2, 4, 6]
|
|
314
|
-
*/
|
|
315
|
-
export const mapAsync =
|
|
316
|
-
<A, B>(fn: (item: A, index: number) => Promise<B>) =>
|
|
317
|
-
(items: readonly A[]): Promise<B[]> =>
|
|
318
|
-
Promise.all(items.map(fn));
|
|
319
|
-
|
|
320
|
-
/**
|
|
321
|
-
* FilterAsync - Filter with async predicate
|
|
322
|
-
*/
|
|
323
|
-
export const filterAsync =
|
|
324
|
-
<A>(predicate: (item: A, index: number) => Promise<boolean>) =>
|
|
325
|
-
async (items: readonly A[]): Promise<A[]> => {
|
|
326
|
-
const results = await Promise.all(items.map(predicate));
|
|
327
|
-
return items.filter((_, i) => results[i]);
|
|
328
|
-
};
|
|
329
|
-
|
|
330
|
-
/**
|
|
331
|
-
* ReduceAsync - Reduce with async function
|
|
332
|
-
*/
|
|
333
|
-
export const reduceAsync =
|
|
334
|
-
<A, B>(fn: (acc: B, item: A, index: number) => Promise<B>, initial: B) =>
|
|
335
|
-
async (items: readonly A[]): Promise<B> => {
|
|
336
|
-
let acc = initial;
|
|
337
|
-
for (let i = 0; i < items.length; i++) {
|
|
338
|
-
acc = await fn(acc, items[i], i);
|
|
339
|
-
}
|
|
340
|
-
return acc;
|
|
341
|
-
};
|
|
342
|
-
|
|
343
|
-
// ============================================================================
|
|
344
|
-
// SIDE EFFECTS & DEBUGGING
|
|
345
|
-
// ============================================================================
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Tap - Execute side effect without changing value
|
|
349
|
-
*
|
|
350
|
-
* @example
|
|
351
|
-
* pipe(
|
|
352
|
-
* 5,
|
|
353
|
-
* x => x * 2,
|
|
354
|
-
* tap((x) => console.log('Debug:', x)), // Logs: Debug: 10
|
|
355
|
-
* x => x + 3
|
|
356
|
-
* ); // 13
|
|
357
|
-
*/
|
|
358
|
-
export const tap =
|
|
359
|
-
<T>(fn: (value: T) => void) =>
|
|
360
|
-
(value: T): T => {
|
|
361
|
-
fn(value);
|
|
362
|
-
return value;
|
|
363
|
-
};
|
|
364
|
-
|
|
365
|
-
/**
|
|
366
|
-
* TapAsync - Execute async side effect
|
|
367
|
-
*/
|
|
368
|
-
export const tapAsync =
|
|
369
|
-
<T>(fn: (value: T) => Promise<void>) =>
|
|
370
|
-
async (value: T): Promise<T> => {
|
|
371
|
-
await fn(value);
|
|
372
|
-
return value;
|
|
373
|
-
};
|
|
374
|
-
|
|
375
|
-
/**
|
|
376
|
-
* Trace - Log value with label
|
|
377
|
-
*
|
|
378
|
-
* @example
|
|
379
|
-
* pipe(
|
|
380
|
-
* 5,
|
|
381
|
-
* x => x * 2,
|
|
382
|
-
* trace('After multiply'), // Logs: "After multiply: 10"
|
|
383
|
-
* x => x + 3
|
|
384
|
-
* );
|
|
385
|
-
*/
|
|
386
|
-
export const trace =
|
|
387
|
-
(label: string) =>
|
|
388
|
-
<T>(value: T): T => {
|
|
389
|
-
console.log(`${label}:`, value);
|
|
390
|
-
return value;
|
|
391
|
-
};
|
|
392
|
-
|
|
393
|
-
// ============================================================================
|
|
394
|
-
// ERROR HANDLING
|
|
395
|
-
// ============================================================================
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* Result type - Represents success or failure
|
|
399
|
-
*/
|
|
400
|
-
export type Result<T, E = Error> = { ok: true; value: T } | { ok: false; error: E };
|
|
401
|
-
|
|
402
|
-
/**
|
|
403
|
-
* TryCatch - Convert exception to Result type
|
|
404
|
-
*
|
|
405
|
-
* @example
|
|
406
|
-
* const result = tryCatch(() => JSON.parse(input));
|
|
407
|
-
* if (result.ok) {
|
|
408
|
-
* console.log(result.value);
|
|
409
|
-
* } else {
|
|
410
|
-
* console.error(result.error);
|
|
411
|
-
* }
|
|
412
|
-
*/
|
|
413
|
-
export const tryCatch = <T, E = Error>(fn: () => T): Result<T, E> => {
|
|
414
|
-
try {
|
|
415
|
-
return { ok: true, value: fn() };
|
|
416
|
-
} catch (error) {
|
|
417
|
-
return { ok: false, error: error as E };
|
|
418
|
-
}
|
|
419
|
-
};
|
|
420
|
-
|
|
421
|
-
/**
|
|
422
|
-
* TryCatchAsync - Async version of tryCatch
|
|
423
|
-
*/
|
|
424
|
-
export const tryCatchAsync = async <T, E = Error>(fn: () => Promise<T>): Promise<Result<T, E>> => {
|
|
425
|
-
try {
|
|
426
|
-
return { ok: true, value: await fn() };
|
|
427
|
-
} catch (error) {
|
|
428
|
-
return { ok: false, error: error as E };
|
|
429
|
-
}
|
|
430
|
-
};
|
|
431
|
-
|
|
432
|
-
/**
|
|
433
|
-
* UnwrapResult - Extract value from Result or throw error
|
|
434
|
-
*/
|
|
435
|
-
export const unwrapResult = <T, E>(result: Result<T, E>): T => {
|
|
436
|
-
if (result.ok) {
|
|
437
|
-
return result.value;
|
|
438
|
-
}
|
|
439
|
-
throw result.error;
|
|
440
|
-
};
|
|
441
|
-
|
|
442
|
-
/**
|
|
443
|
-
* MapResult - Transform Result value
|
|
444
|
-
*/
|
|
445
|
-
export const mapResult =
|
|
446
|
-
<T, U, E>(fn: (value: T) => U) =>
|
|
447
|
-
(result: Result<T, E>): Result<U, E> => {
|
|
448
|
-
if (result.ok) {
|
|
449
|
-
return { ok: true, value: fn(result.value) };
|
|
450
|
-
}
|
|
451
|
-
return result;
|
|
452
|
-
};
|
|
453
|
-
|
|
454
|
-
// ============================================================================
|
|
455
|
-
// PREDICATES & LOGIC
|
|
456
|
-
// ============================================================================
|
|
457
|
-
|
|
458
|
-
/**
|
|
459
|
-
* Not - Negate predicate
|
|
460
|
-
*/
|
|
461
|
-
export const not =
|
|
462
|
-
<A>(predicate: (item: A) => boolean) =>
|
|
463
|
-
(item: A): boolean =>
|
|
464
|
-
!predicate(item);
|
|
465
|
-
|
|
466
|
-
/**
|
|
467
|
-
* And - Combine predicates with AND
|
|
468
|
-
*/
|
|
469
|
-
export const and =
|
|
470
|
-
<A>(...predicates: Array<(item: A) => boolean>) =>
|
|
471
|
-
(item: A): boolean =>
|
|
472
|
-
predicates.every((p) => p(item));
|
|
473
|
-
|
|
474
|
-
/**
|
|
475
|
-
* Or - Combine predicates with OR
|
|
476
|
-
*/
|
|
477
|
-
export const or =
|
|
478
|
-
<A>(...predicates: Array<(item: A) => boolean>) =>
|
|
479
|
-
(item: A): boolean =>
|
|
480
|
-
predicates.some((p) => p(item));
|
|
481
|
-
|
|
482
|
-
// ============================================================================
|
|
483
|
-
// UTILITIES
|
|
484
|
-
// ============================================================================
|
|
485
|
-
|
|
486
|
-
/**
|
|
487
|
-
* Identity - Return value as-is
|
|
488
|
-
*/
|
|
489
|
-
export const identity = <T>(value: T): T => value;
|
|
490
|
-
|
|
491
|
-
/**
|
|
492
|
-
* Constant - Always return same value
|
|
493
|
-
*/
|
|
494
|
-
export const constant =
|
|
495
|
-
<T>(value: T) =>
|
|
496
|
-
(): T =>
|
|
497
|
-
value;
|
|
498
|
-
|
|
499
|
-
/**
|
|
500
|
-
* Noop - Do nothing
|
|
501
|
-
*/
|
|
502
|
-
export const noop = (): void => {};
|
|
503
|
-
|
|
504
|
-
/**
|
|
505
|
-
* Prop - Extract property value
|
|
506
|
-
*
|
|
507
|
-
* @example
|
|
508
|
-
* pipe(
|
|
509
|
-
* [{ name: 'Alice' }, { name: 'Bob' }],
|
|
510
|
-
* map(prop('name'))
|
|
511
|
-
* ); // ['Alice', 'Bob']
|
|
512
|
-
*/
|
|
513
|
-
export const prop =
|
|
514
|
-
<K extends string | number | symbol>(key: K) =>
|
|
515
|
-
<T extends Record<K, any>>(obj: T): T[K] =>
|
|
516
|
-
obj[key];
|
|
517
|
-
|
|
518
|
-
/**
|
|
519
|
-
* Pick - Pick properties from object
|
|
520
|
-
*/
|
|
521
|
-
export const pick =
|
|
522
|
-
<T, K extends keyof T>(keys: K[]) =>
|
|
523
|
-
(obj: T): Pick<T, K> =>
|
|
524
|
-
keys.reduce(
|
|
525
|
-
(acc, key) => {
|
|
526
|
-
acc[key] = obj[key];
|
|
527
|
-
return acc;
|
|
528
|
-
},
|
|
529
|
-
{} as Pick<T, K>
|
|
530
|
-
);
|
|
531
|
-
|
|
532
|
-
/**
|
|
533
|
-
* Omit - Omit properties from object
|
|
534
|
-
*/
|
|
535
|
-
export const omit =
|
|
536
|
-
<T, K extends keyof T>(keys: K[]) =>
|
|
537
|
-
(obj: T): Omit<T, K> => {
|
|
538
|
-
const result = { ...obj };
|
|
539
|
-
for (const key of keys) {
|
|
540
|
-
delete result[key];
|
|
541
|
-
}
|
|
542
|
-
return result;
|
|
543
|
-
};
|