pepka 1.5.3 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bundle.cjs CHANGED
@@ -136,7 +136,6 @@ const qstartsWithWith = (comparator) => curry2((start, s) => {
136
136
  return true;
137
137
  });
138
138
 
139
- // TODO: qoverProp, qover array ?
140
139
  /** Then next fns seem to be excess due to their safe ver performance should be the same or better:
141
140
  * qflat, qpick
142
141
  */
@@ -144,7 +143,7 @@ const qappend = curry2((s, xs) => { xs.push(s); return xs; });
144
143
  const qassoc = curry3((prop, v, obj) => { obj[prop] = v; return obj; });
145
144
  const qreduce = curry3((fn, accum, arr) => arr.reduce(fn, accum));
146
145
  // strategy is for arrays: 1->clean, 2->merge, 3->push.
147
- const mergeDeep$1 = curry3((strategy, o1, o2) => {
146
+ const mergeDeep$1 = (strategy) => curry2((o1, o2) => {
148
147
  for (let k in o2) {
149
148
  switch (type(o2[k])) {
150
149
  case 'Array':
@@ -154,7 +153,7 @@ const mergeDeep$1 = curry3((strategy, o1, o2) => {
154
153
  const o1k = o1[k], o2k = o2[k];
155
154
  for (const i in o2k)
156
155
  if (o1k[i])
157
- mergeDeep$1(strategy, o1k[i], o2k[i]);
156
+ mergeDeep$1(strategy)(o1k[i], o2k[i]);
158
157
  else
159
158
  o1k[i] = o2k[i];
160
159
  break;
@@ -165,7 +164,7 @@ const mergeDeep$1 = curry3((strategy, o1, o2) => {
165
164
  break;
166
165
  case 'Object':
167
166
  if (type(o1[k]) === 'Object') {
168
- mergeDeep$1(strategy, o1[k], o2[k]);
167
+ mergeDeep$1(strategy)(o1[k], o2[k]);
169
168
  break;
170
169
  }
171
170
  default:
@@ -195,7 +194,7 @@ const qmapKeys = curry2((keyMap, o) => {
195
194
  return o;
196
195
  });
197
196
  const qmap = curry2((pipe, arr) => {
198
- for (let i in arr)
197
+ for (const i in arr)
199
198
  arr[i] = pipe(arr[i], +i, arr);
200
199
  return arr;
201
200
  });
@@ -247,6 +246,8 @@ const qreverse = (arr) => arr.reverse();
247
246
  const qomit = curry2((props, o) => qfilter((_, k) => !includes(k, props), o));
248
247
  /** @param start string | any[] @param s string | any[] */
249
248
  const qstartsWith = qstartsWithWith(eq);
249
+ /** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
250
+ const qoverProp = curry3((prop, pipe, data) => qassoc(prop, pipe(data[prop]), data));
250
251
 
251
252
  // TODO: possibly introduce a second argument limiting unfolding.
252
253
  const uncurry = (fn) => (...args) => qreduce(((fn, arg) => fn ? fn(arg) : fn), fn, args);
@@ -273,10 +274,14 @@ const bind = curry2((fn, context) => fn.bind(context));
273
274
  const nth = curry2((i, data) => data[i]);
274
275
  const slice = curry3((from, to, o) => o.slice(from, (isNum(to) ? to : inf)));
275
276
  const flip = (fn) => curry2((b, a) => fn(a, b));
276
- /** @returns first element of an array. */
277
+ /** @returns first element of an array or a string. */
277
278
  const head = nth(0);
278
- /** @returns last element of an array. */
279
+ /** @returns last element of an array or a string. */
279
280
  const tail = slice(1, inf);
281
+ /** Returns last element of an array, readonly array or a string.
282
+ * @param s Array to extract that element.
283
+ * @returns undefined if s is empty or last element. */
284
+ const last = (s) => s[length(s) - 1];
280
285
  /** @param a @param b @returns a+b */
281
286
  const add = curry2((a, b) => a + b);
282
287
  /** @param a @param b @returns b-a */
@@ -295,11 +300,10 @@ const sort = curry2((sortFn, xs) => xs.sort(sortFn));
295
300
  const find = curry2((fn, s) => s.find(fn));
296
301
  const findIndex = curry2((fn, s) => s.findIndex(fn));
297
302
  const indexOf = curry2((x, xs) => findIndex(equals(x), xs));
298
- const divide = curry2((n, m) => n / m);
303
+ const divide = curry2((a, b) => b / a);
299
304
  const always = (s) => () => s;
300
305
  const identity = (s) => s;
301
306
  const trim = (s) => s.trim();
302
- const last = (s) => s[length(s) - 1];
303
307
  /** @param start string | any[] @param s string | any[] */
304
308
  const startsWith = qstartsWithWith((x, y) => equals(x, y));
305
309
  const not = (x) => !x;
@@ -343,14 +347,13 @@ const range = curry2((from, to) => genBy(add(from), to - from));
343
347
  const uniq = (xs) => qreduce((accum, x) => find(equals(x), accum) ? accum : qappend(x, accum), [], xs);
344
348
  const intersection = curry2((xs1, xs2) => xs1.filter(flip(includes)(xs2)));
345
349
  const diff = curry2((_xs1, _xs2) => {
346
- // BUG: if _xs1 is empty, results in [undefined, ...]
347
350
  let len1 = length(_xs1);
348
- let len2 = length(_xs2); // xs2 should be shorter 4 Set mem consumption.
349
- const xs1 = len1 > len2 ? _xs1 : _xs2; // ['qwe', 'qwe2'].
350
- const xs2 = len1 > len2 ? _xs2 : _xs1; // [].
351
- if (len1 <= len2)
351
+ let len2 = length(_xs2);
352
+ const xs1 = len1 > len2 ? _xs1 : _xs2;
353
+ const xs2 = len1 > len2 ? _xs2 : _xs1;
354
+ if (len1 < len2)
352
355
  [len1, len2] = [len2, len1];
353
- const xset2 = new Set(xs2); // empty set.
356
+ const xset2 = new Set(xs2);
354
357
  const common = new Set();
355
358
  const out = [];
356
359
  let i;
@@ -378,7 +381,10 @@ const once = (fn) => {
378
381
  return cache = fn(...args);
379
382
  };
380
383
  };
381
- const reverse = (xs) => compose((ln) => reduce((nxs, _, i) => qappend(xs[ln - i], nxs), [], xs), add(-1), length)(xs);
384
+ const reverse = (xs) => {
385
+ const ln = length(xs) - 1;
386
+ return map((_, i) => xs[ln - i], xs);
387
+ };
382
388
  const explore = (caption, level = 'log') => tap((v) => console[level](caption, v));
383
389
  const cond = curry2((pairs, s) => {
384
390
  for (const [cond, fn] of pairs)
@@ -444,7 +450,6 @@ const freezeShallow = (o) => qfreezeShallow(clone(o));
444
450
  * @param array T2[]
445
451
  */
446
452
  const reduce = curry3((reducer, accum, arr) => qreduce(reducer, clone(accum), arr));
447
- const pickBy = curry2((cond, o) => filter(cond, o));
448
453
  const pick = curry2((props, o) => {
449
454
  const out = {};
450
455
  for (const p of props)
@@ -452,6 +457,7 @@ const pick = curry2((props, o) => {
452
457
  out[p] = o[p];
453
458
  return out;
454
459
  });
460
+ const pickBy = curry2((cond, o) => compose(flip(pick)(o), qfilter(cond), keys)(o));
455
461
  const omit = curry2((props, o) => filter((_, k) => !includes(k, props), o));
456
462
  const fromPairs = (pairs) => Object.fromEntries(pairs);
457
463
  const concat = curry2(((a, b) => b.concat(a)));
@@ -502,9 +508,10 @@ const memoize = curry2((keyGen, fn) => {
502
508
  };
503
509
  });
504
510
  const mergeShallow = curry2((o1, o2) => Object.assign({}, o1, o2));
505
- const mergeDeep = curry2((a, b) => qmergeDeep(clone(a), clone(b)));
506
- const mergeDeepX = curry2((a, b) => qmergeDeepX(clone(a), clone(b)));
507
- const mergeDeepAdd = curry2((a, b) => qmergeDeepAdd(clone(a), clone(b)));
511
+ const mergeDeep = curry2((a, b) => qmergeDeep(clone(a), b));
512
+ const mergeDeepX = curry2((a, b) => qmergeDeepX(clone(a), b));
513
+ const mergeDeepAdd = curry2((a, b) => qmergeDeepAdd(clone(a), b));
514
+ /** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
508
515
  const overProp = curry3((prop, pipe, data) => assoc(prop, pipe(data[prop]), data));
509
516
  /** mapKeys({ a: 'b' }, { a: 44 }) -> { b: 44 } */
510
517
  const mapKeys = curry2((keyMap, o) => qmapKeys(keyMap, Object.assign({}, o)));
@@ -529,12 +536,12 @@ const some = any;
529
536
  const ecran = '\\';
530
537
  // TODO: make it splicy, not accumulatie by symbols.
531
538
  /** Supports ecrans: '\\{"json": {yes} \\}'
532
- @returns get_tmpl(one{meme}two)({meme: 42}) -> one42two */
539
+ @returns getTmpl('one{meme}two')({meme: 42}) -> one42two */
533
540
  const getTmpl = (tmpl) => {
534
541
  const parts = [];
535
542
  const keymap = [];
536
543
  const len = tmpl.length;
537
- let i = 0, s, ln, start = 0, open = false, hasEcran = head(tmpl), hasEcranNext = false, nextChar;
544
+ let i = 0, s, ln, start = 0, open = false, hasEcran = false, hasEcranNext = false, nextChar;
538
545
  for (i = 0; i < len; i++) {
539
546
  s = tmpl[i];
540
547
  switch (s) {
@@ -713,6 +720,7 @@ exports.qmergeDeepAdd = qmergeDeepAdd;
713
720
  exports.qmergeDeepX = qmergeDeepX;
714
721
  exports.qmergeShallow = qmergeShallow;
715
722
  exports.qomit = qomit;
723
+ exports.qoverProp = qoverProp;
716
724
  exports.qprepend = qprepend;
717
725
  exports.qreduce = qreduce;
718
726
  exports.qreverse = qreverse;
package/dist/bundle.d.ts CHANGED
@@ -1,15 +1,21 @@
1
1
  // Generated by dts-bundle-generator v9.5.1
2
2
 
3
+ type AnyArgs = any[];
4
+ type AnyArray<T = any> = T[] | readonly T[];
5
+ type Split<S extends string> = S extends `${infer U}${infer V}` ? [
6
+ U,
7
+ ...Split<V>
8
+ ] : [
9
+ ];
10
+ type IndexesOfArray<A> = Exclude<keyof A, keyof [
11
+ ]>;
3
12
  export type Cond = (x1?: any, x2?: any, x3?: any) => boolean;
4
13
  export interface AnyObject {
5
14
  [k: string]: any;
6
15
  }
7
- export type AnyArgs = any[];
8
16
  export type Reducer<T = any> = (accum: T, cur: any, index: number) => T;
9
17
  export type AnyFunc<ReturnT = any, Args extends AnyArgs = AnyArgs> = (...args: Args) => ReturnT;
10
- export type TupleFn<ARG1 = any, ARG2 = any, Out = any> = (a: ARG1, b: ARG2) => Out;
11
18
  export type Curried<Args extends AnyArgs = AnyArgs, ReturnT = any> = (arg: Args[number]) => Curried<Args> | ReturnT;
12
- export type BasicType = "String" | "Object" | "Number" | "Symbol" | "Array" | "Null" | "Undefined";
13
19
  type Placeholder = symbol;
14
20
  export declare const __: Placeholder;
15
21
  export declare const curry: (fn: AnyFunc) => (...args: AnyArgs) => any;
@@ -33,7 +39,7 @@ export declare const typeIs: {
33
39
  (a: string): (b: any) => boolean;
34
40
  (a: string, b: any): boolean;
35
41
  };
36
- declare const length$1: (s: any[] | string) => number;
42
+ declare const length$1: (s: AnyArray | string) => number;
37
43
  export declare const isNil: (s: any) => boolean;
38
44
  export declare const eq: {
39
45
  (a: symbol, b: any): (a: any) => boolean;
@@ -78,10 +84,10 @@ export declare const bind: {
78
84
  (a: any, b: any): any;
79
85
  };
80
86
  export declare const nth: {
81
- (a: symbol, b: string | unknown[]): (a: number) => unknown;
82
- (a: number, b: symbol): (b: string | unknown[]) => unknown;
83
- (a: number): (b: string | unknown[]) => unknown;
84
- (a: number, b: string | unknown[]): unknown;
87
+ (a: symbol, b: string | any[]): (a: number) => any;
88
+ (a: number, b: symbol): (b: string | any[]) => any;
89
+ (a: number): (b: string | any[]) => any;
90
+ (a: number, b: string | any[]): any;
85
91
  };
86
92
  export declare const slice: (...args: AnyArgs) => any;
87
93
  export declare const flip: <T extends AnyFunc>(fn: T) => {
@@ -90,10 +96,42 @@ export declare const flip: <T extends AnyFunc>(fn: T) => {
90
96
  (a: Parameters<T>[1]): (b: Parameters<T>[0]) => any;
91
97
  (a: Parameters<T>[1], b: Parameters<T>[0]): any;
92
98
  };
93
- /** @returns first element of an array. */
94
- export declare const head: <T = any>(xs: T[] | string) => T;
95
- /** @returns last element of an array. */
96
- export declare const tail: any;
99
+ type FirstChar<T extends string> = T extends `${infer First}${string}` ? Split<T>["length"] extends 1 ? T : FirstChar<First> : T;
100
+ type HeadOverload = {
101
+ <T extends string>(s: T): FirstChar<T>;
102
+ <T extends readonly any[]>(s: T): T extends Array<0> ? undefined : T extends readonly [
103
+ infer U,
104
+ ...any[]
105
+ ] ? U : T extends (infer Y)[] ? Y : any;
106
+ <T extends any>(s: T[]): null;
107
+ };
108
+ /** @returns first element of an array or a string. */
109
+ export declare const head: HeadOverload;
110
+ type Tail<T extends string> = T extends `${string}${infer Tail}` ? Tail : T extends "" ? "" : string;
111
+ type TailOverload = {
112
+ <T extends string>(s: T): Tail<T>;
113
+ <T extends readonly any[]>(s: T): T extends Array<0> ? [
114
+ ] : T extends readonly [
115
+ any,
116
+ ...infer U
117
+ ] ? U : T;
118
+ <T extends any>(s: T[]): null;
119
+ };
120
+ /** @returns last element of an array or a string. */
121
+ export declare const tail: TailOverload;
122
+ type LastChar<T extends string> = T extends `${string}${infer Rest}` ? (Split<T>["length"] extends 1 ? T : LastChar<Rest>) : T;
123
+ type LastOverload = {
124
+ <T extends string>(s: T): LastChar<T>;
125
+ <T extends readonly any[]>(s: T): T extends Array<0> ? undefined : T extends readonly [
126
+ ...any[],
127
+ infer U
128
+ ] ? U : T extends (infer Y)[] ? Y : any;
129
+ <T extends any>(s: T[]): null;
130
+ };
131
+ /** Returns last element of an array, readonly array or a string.
132
+ * @param s Array to extract that element.
133
+ * @returns undefined if s is empty or last element. */
134
+ export declare const last: LastOverload;
97
135
  /** @param a @param b @returns a+b */
98
136
  export declare const add: {
99
137
  (a: symbol, b: number): (a: number) => number;
@@ -144,10 +182,10 @@ export declare const lte: {
144
182
  (a: number, b: number): boolean;
145
183
  };
146
184
  export declare const sort: {
147
- (a: symbol, b: any[]): (a: any) => any[];
148
- (a: any, b: symbol): (b: any[]) => any[];
149
- (a: any): (b: any[]) => any[];
150
- (a: any, b: any[]): any[];
185
+ (a: symbol, b: any[]): (a: (a: any, b: any) => number) => any[];
186
+ (a: (a: any, b: any) => number, b: symbol): (b: any[]) => any[];
187
+ (a: (a: any, b: any) => number): (b: any[]) => any[];
188
+ (a: (a: any, b: any) => number, b: any[]): any[];
151
189
  };
152
190
  export declare const find: {
153
191
  (a: symbol, b: any[]): (a: Cond) => any;
@@ -174,9 +212,8 @@ export declare const divide: {
174
212
  (a: number, b: number): number;
175
213
  };
176
214
  export declare const always: <T = any>(s: T) => () => T;
177
- export declare const identity: (s: any) => any;
215
+ export declare const identity: <T = any>(s: T) => T;
178
216
  export declare const trim: (s: string) => string;
179
- export declare const last: (s: any[] | string) => any;
180
217
  /** @param start string | any[] @param s string | any[] */
181
218
  export declare const startsWith: {
182
219
  (a: symbol, b: string | any[]): (a: string | any[]) => boolean;
@@ -190,11 +227,9 @@ type NotOverload = {
190
227
  (x: any): boolean;
191
228
  };
192
229
  export declare const not: NotOverload;
193
- type IndexesOfArray<A> = Exclude<keyof A, keyof [
194
- ]>;
195
230
  type KeysOverload = {
196
- <T extends any[]>(o: T): string[];
197
231
  <T extends readonly any[]>(o: T): IndexesOfArray<T>[];
232
+ <T extends any[]>(o: T): string[];
198
233
  <T extends AnyObject>(o: T): (keyof T)[];
199
234
  };
200
235
  export declare const keys: KeysOverload;
@@ -284,7 +319,7 @@ export declare const genBy: {
284
319
  (a: (i: number) => any, b: number): any[];
285
320
  };
286
321
  export declare const once: <Func extends AnyFunc>(fn: Func) => (...args: Parameters<Func>) => any;
287
- export declare const reverse: (xs: any[]) => any;
322
+ export declare const reverse: <T extends unknown>(xs: T[]) => T[];
288
323
  export declare const explore: (caption: string, level?: string) => (b: any) => any;
289
324
  export declare const cond: {
290
325
  (a: symbol, b: any): (a: [
@@ -361,18 +396,18 @@ export declare const freezeShallow: <T extends AnyObject>(o: T) => Readonly<T>;
361
396
  * @param array T2[]
362
397
  */
363
398
  export declare const reduce: (...args: AnyArgs) => any;
364
- export declare const pickBy: {
365
- (a: symbol, b: AnyObject): (a: Cond) => any;
366
- (a: Cond, b: symbol): (b: AnyObject) => any;
367
- (a: Cond): (b: AnyObject) => any;
368
- (a: Cond, b: AnyObject): any;
369
- };
370
399
  export declare const pick: {
371
400
  (a: symbol, b: AnyObject): (a: string[]) => {};
372
401
  (a: string[], b: symbol): (b: AnyObject) => {};
373
402
  (a: string[]): (b: AnyObject) => {};
374
403
  (a: string[], b: AnyObject): {};
375
404
  };
405
+ export declare const pickBy: {
406
+ (a: symbol, b: AnyObject): (a: Cond) => any;
407
+ (a: Cond, b: symbol): (b: AnyObject) => any;
408
+ (a: Cond): (b: AnyObject) => any;
409
+ (a: Cond, b: AnyObject): any;
410
+ };
376
411
  export declare const omit: {
377
412
  (a: symbol, b: AnyObject): (a: string[]) => any;
378
413
  (a: string[], b: symbol): (b: AnyObject) => any;
@@ -459,6 +494,7 @@ export declare const mergeDeepAdd: {
459
494
  (a: AnyObject): (b: AnyObject) => AnyObject;
460
495
  (a: AnyObject, b: AnyObject): AnyObject;
461
496
  };
497
+ /** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
462
498
  export declare const overProp: (...args: AnyArgs) => any;
463
499
  /** mapKeys({ a: 'b' }, { a: 44 }) -> { b: 44 } */
464
500
  export declare const mapKeys: {
@@ -494,9 +530,9 @@ export declare const zipObj: {
494
530
  * @param b T2[]
495
531
  */
496
532
  export declare const zipWith: (...args: AnyArgs) => any;
497
- export declare const mirror: (s: any) => any;
498
- export declare const reflect: (s: any) => any;
499
- export declare const echo: (s: any) => any;
533
+ export declare const mirror: <T = any>(s: T) => T;
534
+ export declare const reflect: <T = any>(s: T) => T;
535
+ export declare const echo: <T = any>(s: T) => T;
500
536
  export declare const notf: (fn: AnyFunc) => (...args: any) => boolean | any;
501
537
  export declare const push: {
502
538
  (a: symbol, b: any[]): (a: any) => any[];
@@ -521,9 +557,24 @@ export declare const qappend: {
521
557
  };
522
558
  export declare const qassoc: (...args: AnyArgs) => any;
523
559
  export declare const qreduce: (...args: AnyArgs) => any;
524
- export declare const qmergeDeep: any;
525
- export declare const qmergeDeepX: any;
526
- export declare const qmergeDeepAdd: any;
560
+ export declare const qmergeDeep: {
561
+ (a: symbol, b: AnyObject): (a: AnyObject) => AnyObject;
562
+ (a: AnyObject, b: symbol): (b: AnyObject) => AnyObject;
563
+ (a: AnyObject): (b: AnyObject) => AnyObject;
564
+ (a: AnyObject, b: AnyObject): AnyObject;
565
+ };
566
+ export declare const qmergeDeepX: {
567
+ (a: symbol, b: AnyObject): (a: AnyObject) => AnyObject;
568
+ (a: AnyObject, b: symbol): (b: AnyObject) => AnyObject;
569
+ (a: AnyObject): (b: AnyObject) => AnyObject;
570
+ (a: AnyObject, b: AnyObject): AnyObject;
571
+ };
572
+ export declare const qmergeDeepAdd: {
573
+ (a: symbol, b: AnyObject): (a: AnyObject) => AnyObject;
574
+ (a: AnyObject, b: symbol): (b: AnyObject) => AnyObject;
575
+ (a: AnyObject): (b: AnyObject) => AnyObject;
576
+ (a: AnyObject, b: AnyObject): AnyObject;
577
+ };
527
578
  export declare const qmergeShallow: {
528
579
  (a: symbol, b: AnyObject): (a: AnyObject) => AnyObject;
529
580
  (a: AnyObject, b: symbol): (b: AnyObject) => AnyObject;
@@ -563,7 +614,8 @@ export declare const qfilter: {
563
614
  (a: (v: any, k: string | number) => boolean): (b: any[] | AnyObject) => any[] | AnyObject;
564
615
  (a: (v: any, k: string | number) => boolean, b: any[] | AnyObject): any[] | AnyObject;
565
616
  };
566
- export declare const qempty: (o: AnyObject | any[]) => any[] | AnyObject;
617
+ export declare const qempty: <T extends any[] | AnyObject>(o: T) => T extends any[] ? [
618
+ ] : {};
567
619
  export declare const qfreeze: <T extends AnyObject>(o: T) => Readonly<T>;
568
620
  export declare const qfreezeShallow: <T extends AnyObject>(o: T) => Readonly<T>;
569
621
  export declare const qprepend: {
@@ -587,9 +639,11 @@ export declare const qstartsWith: {
587
639
  (a: string | any[]): (b: string | any[]) => boolean;
588
640
  (a: string | any[], b: string | any[]): boolean;
589
641
  };
642
+ /** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
643
+ export declare const qoverProp: (...args: AnyArgs) => any;
590
644
  type StrTmpl = ((data: AnyObject) => string);
591
645
  /** Supports ecrans: '\\{"json": {yes} \\}'
592
- @returns get_tmpl(one{meme}two)({meme: 42}) -> one42two */
646
+ @returns getTmpl('one{meme}two')({meme: 42}) -> one42two */
593
647
  export declare const getTmpl: (tmpl: string) => StrTmpl;
594
648
  /** One promise waits for another. */
595
649
  export declare const forEachSerial: {
package/dist/bundle.mjs CHANGED
@@ -134,7 +134,6 @@ const qstartsWithWith = (comparator) => curry2((start, s) => {
134
134
  return true;
135
135
  });
136
136
 
137
- // TODO: qoverProp, qover array ?
138
137
  /** Then next fns seem to be excess due to their safe ver performance should be the same or better:
139
138
  * qflat, qpick
140
139
  */
@@ -142,7 +141,7 @@ const qappend = curry2((s, xs) => { xs.push(s); return xs; });
142
141
  const qassoc = curry3((prop, v, obj) => { obj[prop] = v; return obj; });
143
142
  const qreduce = curry3((fn, accum, arr) => arr.reduce(fn, accum));
144
143
  // strategy is for arrays: 1->clean, 2->merge, 3->push.
145
- const mergeDeep$1 = curry3((strategy, o1, o2) => {
144
+ const mergeDeep$1 = (strategy) => curry2((o1, o2) => {
146
145
  for (let k in o2) {
147
146
  switch (type(o2[k])) {
148
147
  case 'Array':
@@ -152,7 +151,7 @@ const mergeDeep$1 = curry3((strategy, o1, o2) => {
152
151
  const o1k = o1[k], o2k = o2[k];
153
152
  for (const i in o2k)
154
153
  if (o1k[i])
155
- mergeDeep$1(strategy, o1k[i], o2k[i]);
154
+ mergeDeep$1(strategy)(o1k[i], o2k[i]);
156
155
  else
157
156
  o1k[i] = o2k[i];
158
157
  break;
@@ -163,7 +162,7 @@ const mergeDeep$1 = curry3((strategy, o1, o2) => {
163
162
  break;
164
163
  case 'Object':
165
164
  if (type(o1[k]) === 'Object') {
166
- mergeDeep$1(strategy, o1[k], o2[k]);
165
+ mergeDeep$1(strategy)(o1[k], o2[k]);
167
166
  break;
168
167
  }
169
168
  default:
@@ -193,7 +192,7 @@ const qmapKeys = curry2((keyMap, o) => {
193
192
  return o;
194
193
  });
195
194
  const qmap = curry2((pipe, arr) => {
196
- for (let i in arr)
195
+ for (const i in arr)
197
196
  arr[i] = pipe(arr[i], +i, arr);
198
197
  return arr;
199
198
  });
@@ -245,6 +244,8 @@ const qreverse = (arr) => arr.reverse();
245
244
  const qomit = curry2((props, o) => qfilter((_, k) => !includes(k, props), o));
246
245
  /** @param start string | any[] @param s string | any[] */
247
246
  const qstartsWith = qstartsWithWith(eq);
247
+ /** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
248
+ const qoverProp = curry3((prop, pipe, data) => qassoc(prop, pipe(data[prop]), data));
248
249
 
249
250
  // TODO: possibly introduce a second argument limiting unfolding.
250
251
  const uncurry = (fn) => (...args) => qreduce(((fn, arg) => fn ? fn(arg) : fn), fn, args);
@@ -271,10 +272,14 @@ const bind = curry2((fn, context) => fn.bind(context));
271
272
  const nth = curry2((i, data) => data[i]);
272
273
  const slice = curry3((from, to, o) => o.slice(from, (isNum(to) ? to : inf)));
273
274
  const flip = (fn) => curry2((b, a) => fn(a, b));
274
- /** @returns first element of an array. */
275
+ /** @returns first element of an array or a string. */
275
276
  const head = nth(0);
276
- /** @returns last element of an array. */
277
+ /** @returns last element of an array or a string. */
277
278
  const tail = slice(1, inf);
279
+ /** Returns last element of an array, readonly array or a string.
280
+ * @param s Array to extract that element.
281
+ * @returns undefined if s is empty or last element. */
282
+ const last = (s) => s[length(s) - 1];
278
283
  /** @param a @param b @returns a+b */
279
284
  const add = curry2((a, b) => a + b);
280
285
  /** @param a @param b @returns b-a */
@@ -293,11 +298,10 @@ const sort = curry2((sortFn, xs) => xs.sort(sortFn));
293
298
  const find = curry2((fn, s) => s.find(fn));
294
299
  const findIndex = curry2((fn, s) => s.findIndex(fn));
295
300
  const indexOf = curry2((x, xs) => findIndex(equals(x), xs));
296
- const divide = curry2((n, m) => n / m);
301
+ const divide = curry2((a, b) => b / a);
297
302
  const always = (s) => () => s;
298
303
  const identity = (s) => s;
299
304
  const trim = (s) => s.trim();
300
- const last = (s) => s[length(s) - 1];
301
305
  /** @param start string | any[] @param s string | any[] */
302
306
  const startsWith = qstartsWithWith((x, y) => equals(x, y));
303
307
  const not = (x) => !x;
@@ -341,14 +345,13 @@ const range = curry2((from, to) => genBy(add(from), to - from));
341
345
  const uniq = (xs) => qreduce((accum, x) => find(equals(x), accum) ? accum : qappend(x, accum), [], xs);
342
346
  const intersection = curry2((xs1, xs2) => xs1.filter(flip(includes)(xs2)));
343
347
  const diff = curry2((_xs1, _xs2) => {
344
- // BUG: if _xs1 is empty, results in [undefined, ...]
345
348
  let len1 = length(_xs1);
346
- let len2 = length(_xs2); // xs2 should be shorter 4 Set mem consumption.
347
- const xs1 = len1 > len2 ? _xs1 : _xs2; // ['qwe', 'qwe2'].
348
- const xs2 = len1 > len2 ? _xs2 : _xs1; // [].
349
- if (len1 <= len2)
349
+ let len2 = length(_xs2);
350
+ const xs1 = len1 > len2 ? _xs1 : _xs2;
351
+ const xs2 = len1 > len2 ? _xs2 : _xs1;
352
+ if (len1 < len2)
350
353
  [len1, len2] = [len2, len1];
351
- const xset2 = new Set(xs2); // empty set.
354
+ const xset2 = new Set(xs2);
352
355
  const common = new Set();
353
356
  const out = [];
354
357
  let i;
@@ -376,7 +379,10 @@ const once = (fn) => {
376
379
  return cache = fn(...args);
377
380
  };
378
381
  };
379
- const reverse = (xs) => compose((ln) => reduce((nxs, _, i) => qappend(xs[ln - i], nxs), [], xs), add(-1), length)(xs);
382
+ const reverse = (xs) => {
383
+ const ln = length(xs) - 1;
384
+ return map((_, i) => xs[ln - i], xs);
385
+ };
380
386
  const explore = (caption, level = 'log') => tap((v) => console[level](caption, v));
381
387
  const cond = curry2((pairs, s) => {
382
388
  for (const [cond, fn] of pairs)
@@ -442,7 +448,6 @@ const freezeShallow = (o) => qfreezeShallow(clone(o));
442
448
  * @param array T2[]
443
449
  */
444
450
  const reduce = curry3((reducer, accum, arr) => qreduce(reducer, clone(accum), arr));
445
- const pickBy = curry2((cond, o) => filter(cond, o));
446
451
  const pick = curry2((props, o) => {
447
452
  const out = {};
448
453
  for (const p of props)
@@ -450,6 +455,7 @@ const pick = curry2((props, o) => {
450
455
  out[p] = o[p];
451
456
  return out;
452
457
  });
458
+ const pickBy = curry2((cond, o) => compose(flip(pick)(o), qfilter(cond), keys)(o));
453
459
  const omit = curry2((props, o) => filter((_, k) => !includes(k, props), o));
454
460
  const fromPairs = (pairs) => Object.fromEntries(pairs);
455
461
  const concat = curry2(((a, b) => b.concat(a)));
@@ -500,9 +506,10 @@ const memoize = curry2((keyGen, fn) => {
500
506
  };
501
507
  });
502
508
  const mergeShallow = curry2((o1, o2) => Object.assign({}, o1, o2));
503
- const mergeDeep = curry2((a, b) => qmergeDeep(clone(a), clone(b)));
504
- const mergeDeepX = curry2((a, b) => qmergeDeepX(clone(a), clone(b)));
505
- const mergeDeepAdd = curry2((a, b) => qmergeDeepAdd(clone(a), clone(b)));
509
+ const mergeDeep = curry2((a, b) => qmergeDeep(clone(a), b));
510
+ const mergeDeepX = curry2((a, b) => qmergeDeepX(clone(a), b));
511
+ const mergeDeepAdd = curry2((a, b) => qmergeDeepAdd(clone(a), b));
512
+ /** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
506
513
  const overProp = curry3((prop, pipe, data) => assoc(prop, pipe(data[prop]), data));
507
514
  /** mapKeys({ a: 'b' }, { a: 44 }) -> { b: 44 } */
508
515
  const mapKeys = curry2((keyMap, o) => qmapKeys(keyMap, Object.assign({}, o)));
@@ -527,12 +534,12 @@ const some = any;
527
534
  const ecran = '\\';
528
535
  // TODO: make it splicy, not accumulatie by symbols.
529
536
  /** Supports ecrans: '\\{"json": {yes} \\}'
530
- @returns get_tmpl(one{meme}two)({meme: 42}) -> one42two */
537
+ @returns getTmpl('one{meme}two')({meme: 42}) -> one42two */
531
538
  const getTmpl = (tmpl) => {
532
539
  const parts = [];
533
540
  const keymap = [];
534
541
  const len = tmpl.length;
535
- let i = 0, s, ln, start = 0, open = false, hasEcran = head(tmpl), hasEcranNext = false, nextChar;
542
+ let i = 0, s, ln, start = 0, open = false, hasEcran = false, hasEcranNext = false, nextChar;
536
543
  for (i = 0; i < len; i++) {
537
544
  s = tmpl[i];
538
545
  switch (s) {
@@ -603,4 +610,4 @@ const composeAsync = (() => {
603
610
  return (...fns) => (...input) => pipe(fns, input, fns.length - 1);
604
611
  })();
605
612
 
606
- export { F, T, __, add, all, allPass, always, any, anyPass, append, assoc, assocPath, bind, both, callFrom, callWith, clone, cloneShallow, complement, compose, composeAsync, concat, cond, curry, curry2, curry3, diff, divide, echo, empty, eq, equals, explore, filter, find, findIndex, flat, flatShallow, flatTo, flip, forEach, forEachAsync, forEachSerial, freeze, freezeShallow, fromPairs, genBy, getTmpl, gt, gte, head, identity, ifElse, includes, indexOf, intersection, isEmpty, isNil, join, keys, last, length, lt, lte, map, mapKeys, mapObj, memoize, mergeDeep, mergeDeepAdd, mergeDeepX, mergeShallow, mirror, multiply, noop, not, notf, nth, omit, once, overProp, path, pathEq, pathExists, pathOr, pathsEq, pick, pickBy, prepend, prop, propEq, propsEq, push, qappend, qassoc, qassocPath, qempty, qfilter, qfreeze, qfreezeShallow, qmap, qmapKeys, qmapObj, qmergeDeep, qmergeDeepAdd, qmergeDeepX, qmergeShallow, qomit, qprepend, qreduce, qreverse, qstartsWith, qstartsWithWith, range, reduce, reflect, replace, reverse, sizeof, slice, some, sort, split, startsWith, subtract, symbol, tail, take, tap, test, toLower, toPairs, toUpper, trim, type, typeIs, uncurry, uniq, values, waitAll, waitTap, weakEq, when, zip, zipObj, zipWith };
613
+ export { F, T, __, add, all, allPass, always, any, anyPass, append, assoc, assocPath, bind, both, callFrom, callWith, clone, cloneShallow, complement, compose, composeAsync, concat, cond, curry, curry2, curry3, diff, divide, echo, empty, eq, equals, explore, filter, find, findIndex, flat, flatShallow, flatTo, flip, forEach, forEachAsync, forEachSerial, freeze, freezeShallow, fromPairs, genBy, getTmpl, gt, gte, head, identity, ifElse, includes, indexOf, intersection, isEmpty, isNil, join, keys, last, length, lt, lte, map, mapKeys, mapObj, memoize, mergeDeep, mergeDeepAdd, mergeDeepX, mergeShallow, mirror, multiply, noop, not, notf, nth, omit, once, overProp, path, pathEq, pathExists, pathOr, pathsEq, pick, pickBy, prepend, prop, propEq, propsEq, push, qappend, qassoc, qassocPath, qempty, qfilter, qfreeze, qfreezeShallow, qmap, qmapKeys, qmapObj, qmergeDeep, qmergeDeepAdd, qmergeDeepX, qmergeShallow, qomit, qoverProp, qprepend, qreduce, qreverse, qstartsWith, qstartsWithWith, range, reduce, reflect, replace, reverse, sizeof, slice, some, sort, split, startsWith, subtract, symbol, tail, take, tap, test, toLower, toPairs, toUpper, trim, type, typeIs, uncurry, uniq, values, waitAll, waitTap, weakEq, when, zip, zipObj, zipWith };
package/package.json CHANGED
@@ -42,7 +42,7 @@
42
42
  "prod": "npm run gentypes && npm run prod:es && npm run prod:cjs",
43
43
  "all": "npm run dev && npm run prod"
44
44
  },
45
- "version": "1.5.3",
45
+ "version": "1.6.0",
46
46
  "ava": {
47
47
  "files": [
48
48
  "./test/specs/*.ts"
@@ -67,7 +67,7 @@
67
67
  "dts-bundle-generator": "^9.5.1",
68
68
  "nyc": "^15.1.0",
69
69
  "prepend": "^1.0.2",
70
- "rollup": "^4.16.1",
70
+ "rollup": "^4.17.0",
71
71
  "rollup-plugin-typescript2": "^0.36.0",
72
72
  "ts-node": "^10.9.2",
73
73
  "tslint": "^6.1.3",
package/src/common.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { curry2 } from "./curry"
2
+ import { AnyArray } from "./internal_types"
2
3
  import { to, isNull, isStr, isUndef } from "./utils"
3
4
 
4
5
  // It's faster that toUpperCase() !
@@ -14,7 +15,7 @@ export const type = (s: any): string => {
14
15
  : caseMap[t[0]] + t.slice(1)
15
16
  }
16
17
  export const typeIs = curry2((t: string, s: any) => type(s)===t)
17
- export const length = (s: any[] | string) => s.length
18
+ export const length = (s: AnyArray | string) => s.length
18
19
  export const isNil = (s: any) => isNull(s) || isUndef(s)
19
20
  export const eq = curry2((a: any, b: any) => a===b)
20
21
  export const equals = curry2((a: any, b: any) => {
package/src/curry.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { AnyFunc, AnyArgs } from "./types"
1
+ import { AnyArgs } from "./internal_types"
2
+ import { AnyFunc } from "./types"
2
3
 
3
4
  type Placeholder = symbol
4
5
  export const __: Placeholder = Symbol('Placeholder')
@@ -0,0 +1,7 @@
1
+ export type AnyArgs = any[]
2
+ export type BasicType = 'String'|'Object'|'Number'|'Symbol'|'Array'|'Null'|'Undefined'
3
+ export type TupleFn<ARG1=any, ARG2=any, Out=any> = (a: ARG1, b: ARG2) => Out
4
+ export type IDArray = Uint8Array|Uint16Array|Uint32Array
5
+ export type AnyArray<T=any> = T[] | readonly T[]
6
+ export type Split<S extends string> = S extends `${infer U}${infer V}` ? [U, ...Split<V>] : []
7
+ export type IndexesOfArray<A> = Exclude<keyof A, keyof []>
package/src/quick.ts CHANGED
@@ -2,8 +2,6 @@ import { curry2, curry3 } from "./curry"
2
2
  import { includes, isNil, type, eq, qstartsWithWith } from "./common"
3
3
  import { AnyObject, Reducer, AnyFunc } from "./types"
4
4
  import { isFunc, isArray, isObj } from "./utils"
5
- // TODO: qoverProp, qover array ?
6
-
7
5
  /** Then next fns seem to be excess due to their safe ver performance should be the same or better:
8
6
  * qflat, qpick
9
7
  */
@@ -12,7 +10,7 @@ export const qappend = curry2((s: any, xs: any[]) => {xs.push(s); return xs})
12
10
  export const qassoc = curry3((prop: string, v: any, obj: AnyObject) => { obj[prop] = v; return obj })
13
11
  export const qreduce = curry3(<T>(fn: Reducer, accum: any, arr: T[]) => arr.reduce(fn, accum))
14
12
  // strategy is for arrays: 1->clean, 2->merge, 3->push.
15
- const mergeDeep = curry3((strategy: 1|2|3, o1: AnyObject, o2: AnyObject): AnyObject => {
13
+ const mergeDeep = (strategy: 1|2|3) => curry2((o1: AnyObject, o2: AnyObject): AnyObject => {
16
14
  for(let k in o2) {
17
15
  switch(type(o2[k])) {
18
16
  case 'Array':
@@ -21,7 +19,7 @@ const mergeDeep = curry3((strategy: 1|2|3, o1: AnyObject, o2: AnyObject): AnyObj
21
19
  case 2:
22
20
  const o1k = o1[k], o2k = o2[k]
23
21
  for(const i in o2k)
24
- if(o1k[i]) mergeDeep(strategy, o1k[i], o2k[i])
22
+ if(o1k[i]) mergeDeep(strategy)(o1k[i], o2k[i])
25
23
  else o1k[i] = o2k[i]
26
24
  break
27
25
  case 3: o1[k].push(...o2[k])
@@ -31,7 +29,7 @@ const mergeDeep = curry3((strategy: 1|2|3, o1: AnyObject, o2: AnyObject): AnyObj
31
29
  break
32
30
  case 'Object':
33
31
  if(type(o1[k])==='Object') {
34
- mergeDeep(strategy, o1[k], o2[k])
32
+ mergeDeep(strategy)(o1[k], o2[k])
35
33
  break
36
34
  }
37
35
  default:
@@ -65,7 +63,7 @@ export const qmapKeys = curry2(
65
63
  )
66
64
  export const qmap = curry2(
67
65
  (pipe: (s: any, i?: number, list?: any[]) => any, arr: any[]) => {
68
- for(let i in arr) arr[i] = pipe(arr[i], +i, arr)
66
+ for(const i in arr) arr[i] = pipe(arr[i], +i, arr)
69
67
  return arr
70
68
  }
71
69
  )
@@ -93,10 +91,10 @@ export const qfilter = curry2(
93
91
  return data
94
92
  }
95
93
  )
96
- export const qempty = (o: AnyObject|any[]) => {
94
+ export const qempty = <T extends AnyObject|any[]>(o: T): T extends any[] ? [] : {} => {
97
95
  if(isArray(o)) o.splice(0)
98
96
  else for(const i in o) delete o[i]
99
- return o
97
+ return o as any
100
98
  }
101
99
  export const qfreeze = <T extends AnyObject>(o: T): Readonly<T> => {
102
100
  let v: any
@@ -124,4 +122,9 @@ export const qomit = curry2(
124
122
  )
125
123
  )
126
124
  /** @param start string | any[] @param s string | any[] */
127
- export const qstartsWith = qstartsWithWith(eq)
125
+ export const qstartsWith = qstartsWithWith(eq)
126
+ /** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
127
+ export const qoverProp = curry3(
128
+ (prop: string, pipe: AnyFunc, data: any) =>
129
+ qassoc(prop, pipe(data[prop]), data)
130
+ )
package/src/safe.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { __, curry, curry2, curry3 } from './curry'
2
- import { isNum, undef, isNull, isArray, isFunc, isObj, inf } from './utils'
2
+ import { isNum, undef, isArray, isFunc, isObj, inf } from './utils'
3
3
  import { qmergeDeep, qreduce, qappend, qmapKeys, qmergeDeepX, qmergeDeepAdd, qfilter, qfreeze, qfreezeShallow, qmapObj } from './quick'
4
4
  import { AnyFunc, Cond, AnyObject, Reducer } from './types'
5
5
  import { symbol, type, length, equals, includes, isNil, qstartsWithWith } from './common'
6
+ import { Split, AnyArray, IndexesOfArray } from './internal_types'
6
7
  // over, lensProp
7
8
 
8
9
  export const take = (argN: number) => (...args: any[]) => args[argN]
@@ -38,10 +39,8 @@ export const compose = (
38
39
  return s as any as TOut
39
40
  }
40
41
  )
41
- export const bind = curry2<AnyFunc>(
42
- (fn: AnyFunc, context: any) => fn.bind(context)
43
- )
44
- export const nth = curry2(<T=any>(i: number, data: T[] | string) => data[i])
42
+ export const bind = curry2<AnyFunc>((fn: AnyFunc, context: any) => fn.bind(context))
43
+ export const nth = curry2((i: number, data: any[] | string) => data[i])
45
44
  export const slice = curry3(
46
45
  (from: number, to: number, o: any[] | string) =>
47
46
  o.slice(from, (isNum(to)?to:inf) as number)
@@ -49,10 +48,42 @@ export const slice = curry3(
49
48
  export const flip = <T extends AnyFunc>(fn: T) => curry2(
50
49
  (b: Parameters<T>[1], a: Parameters<T>[0]) => fn(a, b)
51
50
  )
52
- /** @returns first element of an array. */
53
- export const head = nth(0) as <T = any>(xs: T[] | string) => T
54
- /** @returns last element of an array. */
55
- export const tail = slice(1, inf)
51
+ type FirstChar<T extends string> = T extends `${infer First}${string}`
52
+ ? Split<T>['length'] extends 1 ? T : FirstChar<First>
53
+ : T
54
+ type HeadOverload = {
55
+ <T extends string>(s: T): FirstChar<T>
56
+ <T extends readonly any[]>(s: T): T extends Array<0> ? undefined
57
+ : T extends readonly [infer U, ...any[]] ? U
58
+ : T extends (infer Y)[] ? Y : any
59
+ <T extends any>(s: T[]): null
60
+ }
61
+ /** @returns first element of an array or a string. */
62
+ export const head = nth(0) as HeadOverload
63
+ type Tail<T extends string> = T extends `${string}${infer Tail}`
64
+ ? Tail : T extends '' ? '' : string
65
+ type TailOverload = {
66
+ <T extends string>(s: T): Tail<T>
67
+ <T extends readonly any[]>(s: T): T extends Array<0> ? []
68
+ : T extends readonly [any, ...infer U] ? U : T
69
+ <T extends any>(s: T[]): null
70
+ }
71
+ /** @returns last element of an array or a string. */
72
+ export const tail = slice(1, inf) as TailOverload
73
+ type LastChar<T extends string> = T extends `${string}${infer Rest}`
74
+ ? (Split<T>['length'] extends 1 ? T : LastChar<Rest>) : T
75
+ type LastOverload = {
76
+ <T extends string>(s: T): LastChar<T>
77
+ <T extends readonly any[]>(s: T): T extends Array<0>
78
+ ? undefined
79
+ : T extends readonly [...any[], infer U] ? U
80
+ : T extends (infer Y)[] ? Y : any
81
+ <T extends any>(s: T[]): null
82
+ }
83
+ /** Returns last element of an array, readonly array or a string.
84
+ * @param s Array to extract that element.
85
+ * @returns undefined if s is empty or last element. */
86
+ export const last: LastOverload = (s: string | AnyArray) => s[length(s)-1]
56
87
  /** @param a @param b @returns a+b */
57
88
  export const add = curry2((a: number, b: number) => a+b)
58
89
  /** @param a @param b @returns b-a */
@@ -67,15 +98,15 @@ export const lt = curry2( (a: number, b: number) => a>b )
67
98
  export const gte = curry2( (a: number, b: number) => a<=b )
68
99
  /** @param a @param b @returns a≥b */
69
100
  export const lte = curry2( (a: number, b: number) => a>=b )
70
- export const sort = curry2((sortFn: any, xs: any[]) => xs.sort(sortFn))
101
+ export const sort = curry2((sortFn: (a: any, b: any) => number , xs: any[]) => xs.sort(sortFn))
71
102
  export const find = curry2((fn: Cond, s: any[]) => s.find(fn))
72
103
  export const findIndex = curry2((fn: Cond, s: any[]) => s.findIndex(fn))
73
104
  export const indexOf = curry2((x: any, xs: any[]) => findIndex(equals(x), xs))
74
- export const divide = curry2((n: number, m: number) => n/m)
105
+ export const divide = curry2((a: number, b: number) => b/a)
75
106
  export const always = <T=any>(s: T) => () => s
76
- export const identity = (s: any) => s
107
+ export const identity = <T=any>(s: T) => s
77
108
  export const trim = (s: string) => s.trim()
78
- export const last = (s: any[] | string) => s[length(s)-1]
109
+
79
110
  /** @param start string | any[] @param s string | any[] */
80
111
  export const startsWith = qstartsWithWith((x: any, y: any) => equals(x, y))
81
112
  type NotOverload = {
@@ -84,14 +115,12 @@ type NotOverload = {
84
115
  (x: any): boolean
85
116
  }
86
117
  export const not: NotOverload = (x: any) => !x as any
87
- type IndexesOfArray<A> = Exclude<keyof A, keyof []>
88
118
  type KeysOverload = {
89
- <T extends any[]>(o: T): string[]
90
119
  <T extends readonly any[]>(o: T): IndexesOfArray<T>[]
120
+ <T extends any[]>(o: T): string[]
91
121
  <T extends AnyObject>(o: T): (keyof T)[]
92
122
  }
93
- export const keys: KeysOverload = (o: number[]) => Object.keys(o)
94
-
123
+ export const keys: KeysOverload = (o: any) => Object.keys(o)
95
124
  export const values = (o: AnyObject | any[]) => Object.values(o)
96
125
  export const toPairs = (o: AnyObject | any[]) => Object.entries(o)
97
126
  export const test = curry2((re: RegExp, s: string) => re.test(s))
@@ -131,13 +160,12 @@ export const uniq = (xs: any[]) => qreduce(
131
160
  [], xs)
132
161
  export const intersection = curry2((xs1: any[], xs2: any[]) => xs1.filter(flip(includes)(xs2)))
133
162
  export const diff = curry2((_xs1: any[], _xs2: any[]) => {
134
- // BUG: if _xs1 is empty, results in [undefined, ...]
135
163
  let len1 = length(_xs1)
136
- let len2 = length(_xs2) // xs2 should be shorter 4 Set mem consumption.
137
- const xs1 = len1>len2 ? _xs1 : _xs2 // ['qwe', 'qwe2'].
138
- const xs2 = len1>len2 ? _xs2 : _xs1 // [].
139
- if(len1<=len2) [len1, len2] = [len2, len1]
140
- const xset2 = new Set(xs2) // empty set.
164
+ let len2 = length(_xs2)
165
+ const xs1 = len1>len2 ? _xs1 : _xs2
166
+ const xs2 = len1>len2 ? _xs2 : _xs1
167
+ if(len1<len2) [len1, len2] = [len2, len1]
168
+ const xset2 = new Set(xs2)
141
169
  const common = new Set()
142
170
  const out: any[] = []
143
171
  let i: number
@@ -166,14 +194,10 @@ export const once = <Func extends AnyFunc>(fn: Func) => {
166
194
  return cache = fn(...args)
167
195
  }
168
196
  }
169
- export const reverse = (xs: any[]) => compose(
170
- <T>(ln: number) => reduce(
171
- (nxs: T[], _: any, i: number) => qappend(xs[ln-i], nxs),
172
- [], xs
173
- ),
174
- add(-1),
175
- length
176
- )(xs)
197
+ export const reverse = <T extends any>(xs: T[]): T[] => {
198
+ const ln = length(xs)-1
199
+ return map((_: any, i: number) => xs[ln-i], xs)
200
+ }
177
201
  export const explore = (caption: string, level = 'log') => tap(
178
202
  (v: any) => console[level](caption, v)
179
203
  )
@@ -266,17 +290,16 @@ export const reduce = curry3(
266
290
  <T = any>(reducer: Reducer<T>, accum: T, arr: any[]) =>
267
291
  qreduce(reducer, clone(accum), arr)
268
292
  )
269
- export const pickBy = curry2(
270
- (cond: Cond, o: AnyObject) => filter(cond, o)
271
- )
272
293
  export const pick = curry2(
273
294
  (props: string[], o: AnyObject) => {
274
295
  const out = {}
275
- for(const p of props)
276
- if(p in o) out[p] = o[p]
296
+ for(const p of props) if(p in o) out[p] = o[p]
277
297
  return out
278
298
  }
279
299
  )
300
+ export const pickBy = curry2(
301
+ (cond: Cond, o: AnyObject) => compose(flip(pick)(o), qfilter(cond), keys)(o)
302
+ )
280
303
  export const omit = curry2(
281
304
  (props: string[], o: AnyObject) => filter(
282
305
  (_: any, k: string) => !includes(k, props),
@@ -354,14 +377,15 @@ export const mergeShallow = curry2(
354
377
  Object.assign({}, o1, o2)
355
378
  )
356
379
  export const mergeDeep = curry2(
357
- (a: AnyObject, b: AnyObject) => qmergeDeep(clone(a), clone(b)) as AnyObject
380
+ (a: AnyObject, b: AnyObject) => qmergeDeep(clone(a), b) as AnyObject
358
381
  )
359
382
  export const mergeDeepX = curry2(
360
- (a: AnyObject, b: AnyObject) => qmergeDeepX(clone(a), clone(b)) as AnyObject
383
+ (a: AnyObject, b: AnyObject) => qmergeDeepX(clone(a), b) as AnyObject
361
384
  )
362
385
  export const mergeDeepAdd = curry2(
363
- (a: AnyObject, b: AnyObject) => qmergeDeepAdd(clone(a), clone(b)) as AnyObject
386
+ (a: AnyObject, b: AnyObject) => qmergeDeepAdd(clone(a), b) as AnyObject
364
387
  )
388
+ /** @param prop string @param pipe(data[prop]) @param data any @returns data with prop over pipe. */
365
389
  export const overProp = curry3(
366
390
  (prop: string, pipe: AnyFunc, data: any) =>
367
391
  assoc(prop, pipe(data[prop]), data)
package/src/strings.ts CHANGED
@@ -6,13 +6,13 @@ const ecran = '\\'
6
6
 
7
7
  // TODO: make it splicy, not accumulatie by symbols.
8
8
  /** Supports ecrans: '\\{"json": {yes} \\}'
9
- @returns get_tmpl(one{meme}two)({meme: 42}) -> one42two */
9
+ @returns getTmpl('one{meme}two')({meme: 42}) -> one42two */
10
10
  export const getTmpl = (tmpl: string): StrTmpl => {
11
11
  const parts: string[] = []
12
12
  const keymap: string[] = []
13
13
  const len = tmpl.length
14
14
  let i = 0, s: string, ln: number, start = 0, open = false,
15
- hasEcran = head(tmpl), hasEcranNext = false, nextChar: string
15
+ hasEcran = false, hasEcranNext = false, nextChar: string
16
16
  for(i=0; i<len; i++) {
17
17
  s = tmpl[i]
18
18
  switch(s) {
package/src/types.ts CHANGED
@@ -1,11 +1,7 @@
1
+ import { AnyArgs } from "./internal_types"
2
+
1
3
  export type Cond = (x1?: any, x2?: any, x3?: any) => boolean
2
4
  export interface AnyObject { [k: string]: any }
3
- export type AnyArgs = any[]
4
5
  export type Reducer<T=any> = (accum: T, cur: any, index: number) => T
5
6
  export type AnyFunc<ReturnT = any, Args extends AnyArgs = AnyArgs> = (...args: Args) => ReturnT
6
- export type TupleFn<ARG1=any, ARG2=any, Out=any> = (a: ARG1, b: ARG2) => Out
7
- export type Curried<
8
- Args extends AnyArgs = AnyArgs,
9
- ReturnT = any
10
- > = (arg: Args[number]) => Curried<Args> | ReturnT
11
- export type BasicType = 'String'|'Object'|'Number'|'Symbol'|'Array'|'Null'|'Undefined'
7
+ export type Curried<Args extends AnyArgs = AnyArgs, ReturnT = any> = (arg: Args[number]) => Curried<Args> | ReturnT