@naturalcycles/js-lib 14.267.2 → 14.269.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.
@@ -173,8 +173,8 @@ export declare function _difference<T>(a1: T[], a2: T[] | Set<T>): T[];
173
173
  /**
174
174
  * Returns the sum of items, or 0 for empty array.
175
175
  */
176
- export declare function _sum(items: Iterable<number>): number;
177
- export declare function _sumBy<T>(items: Iterable<T>, mapper: Mapper<T, number | undefined>): number;
176
+ export declare function _sum<N extends number>(items: Iterable<N>): N;
177
+ export declare function _sumBy<T, N extends number>(items: Iterable<T>, mapper: Mapper<T, N | undefined>): N;
178
178
  /**
179
179
  * Map an array of T to a StringMap<V>,
180
180
  * by returning a tuple of [key, value] from a mapper function.
@@ -336,7 +336,7 @@ function _difference(a1, a2) {
336
336
  function _sum(items) {
337
337
  let sum = 0;
338
338
  for (const n of items) {
339
- sum += n;
339
+ sum = (sum + n);
340
340
  }
341
341
  return sum;
342
342
  }
@@ -347,7 +347,7 @@ function _sumBy(items, mapper) {
347
347
  const v = mapper(n, i++);
348
348
  if (typeof v === 'number') {
349
349
  // count only numbers, nothing else
350
- sum += v;
350
+ sum = (sum + v);
351
351
  }
352
352
  }
353
353
  return sum;
@@ -1,7 +1,7 @@
1
1
  import type { CommonLogger } from '../log/commonLogger';
2
- import { AnyAsyncFunction, AnyFunction, AnyObject } from '../types';
3
- import { AsyncMemoCache } from './memo.util';
4
- export interface AsyncMemoOptions {
2
+ import { AnyAsyncFunction, AnyFunction, AnyObject, MaybeParameters } from '../types';
3
+ import { AsyncMemoCache, MethodDecorator } from './memo.util';
4
+ export interface AsyncMemoOptions<T> {
5
5
  /**
6
6
  * Provide a custom implementation of AsyncMemoCache.
7
7
  * Function that creates an instance of `AsyncMemoCache`.
@@ -10,7 +10,7 @@ export interface AsyncMemoOptions {
10
10
  /**
11
11
  * Provide a custom implementation of CacheKey function.
12
12
  */
13
- cacheKeyFn?: (args: any[]) => any;
13
+ cacheKeyFn?: (args: MaybeParameters<T>) => any;
14
14
  /**
15
15
  * Default to `console`
16
16
  */
@@ -32,7 +32,7 @@ export interface AsyncMemoInstance {
32
32
  *
33
33
  * @experimental consider normal @_Memo for most of the cases, it's stable and predictable
34
34
  */
35
- export declare const _AsyncMemo: (opt: AsyncMemoOptions) => MethodDecorator;
35
+ export declare const _AsyncMemo: <T>(opt: AsyncMemoOptions<T>) => MethodDecorator<T>;
36
36
  /**
37
37
  Call it on a method that is decorated with `@_AsyncMemo` to get access to additional functions,
38
38
  e.g `clear` to clear the cache, or get its underlying data.
@@ -16,9 +16,7 @@ const memo_util_1 = require("./memo.util");
16
16
  */
17
17
  // eslint-disable-next-line @typescript-eslint/naming-convention
18
18
  const _AsyncMemo = (opt) => (target, key, descriptor) => {
19
- if (typeof descriptor.value !== 'function') {
20
- throw new TypeError('Memoization can be applied only to methods');
21
- }
19
+ (0, assert_1._assertTypeOf)(descriptor.value, 'function', 'Memoization can be applied only to methods');
22
20
  const originalFn = descriptor.value;
23
21
  // Map from "instance" of the Class where @_AsyncMemo is applied to AsyncMemoCache instance.
24
22
  const instanceCache = new Map();
@@ -1,7 +1,8 @@
1
1
  import type { CommonLogger } from '../log/commonLogger';
2
- import { AnyFunction, AnyObject } from '../types';
2
+ import { AnyFunction, AnyObject, MaybeParameters } from '../types';
3
3
  import type { MemoCache } from './memo.util';
4
- export interface MemoOptions {
4
+ import { MethodDecorator } from './memo.util';
5
+ export interface MemoOptions<T> {
5
6
  /**
6
7
  * Provide a custom implementation of MemoCache.
7
8
  * Function that creates an instance of `MemoCache`.
@@ -11,7 +12,7 @@ export interface MemoOptions {
11
12
  /**
12
13
  * Provide a custom implementation of CacheKey function.
13
14
  */
14
- cacheKeyFn?: (args: any[]) => any;
15
+ cacheKeyFn?: (args: MaybeParameters<T>) => any;
15
16
  /**
16
17
  * Default to `console`
17
18
  */
@@ -45,7 +46,7 @@ export interface MemoInstance {
45
46
  * http://inlehmansterms.net/2015/03/01/javascript-memoization/
46
47
  * https://community.risingstack.com/the-worlds-fastest-javascript-memoization-library/
47
48
  */
48
- export declare const _Memo: (opt?: MemoOptions) => MethodDecorator;
49
+ export declare const _Memo: <T>(opt?: MemoOptions<T>) => MethodDecorator<T>;
49
50
  /**
50
51
  Call it on a method that is decorated with `@_Memo` to get access to additional functions,
51
52
  e.g `clear` to clear the cache, or get its underlying data.
@@ -28,9 +28,7 @@ const memo_util_1 = require("./memo.util");
28
28
  */
29
29
  // eslint-disable-next-line @typescript-eslint/naming-convention
30
30
  const _Memo = (opt = {}) => (target, key, descriptor) => {
31
- if (typeof descriptor.value !== 'function') {
32
- throw new TypeError('Memoization can be applied only to methods');
33
- }
31
+ (0, assert_1._assertTypeOf)(descriptor.value, 'function', 'Memoization can be applied only to methods');
34
32
  const originalFn = descriptor.value;
35
33
  // Map<ctx => MemoCache<cacheKey, result>>
36
34
  //
@@ -1,4 +1,4 @@
1
- import type { UnixTimestamp } from '../types';
1
+ import type { AnyObject, UnixTimestamp } from '../types';
2
2
  import { MISS } from '../types';
3
3
  export type MemoSerializer = (args: any[]) => any;
4
4
  export declare const jsonMemoSerializer: MemoSerializer;
@@ -59,3 +59,9 @@ export declare class MapAsyncMemoCache<KEY = any, VALUE = any> implements AsyncM
59
59
  set(k: KEY, v: VALUE): Promise<void>;
60
60
  clear(): Promise<void>;
61
61
  }
62
+ /**
63
+ * Generic override of Typescript's built in legacy MethodDecorator, that
64
+ * allows us to infer the parameters of the decorated method from the parameters
65
+ * of a decorator.
66
+ */
67
+ export type MethodDecorator<T> = (target: AnyObject, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | undefined;
@@ -1,3 +1,4 @@
1
+ import { AnyFunction } from '../types';
1
2
  import type { MemoOptions } from './memo.decorator';
2
3
  import type { MemoCache } from './memo.util';
3
4
  export interface MemoizedFunction {
@@ -10,4 +11,4 @@ export interface MemoizedFunction {
10
11
  *
11
12
  * @experimental
12
13
  */
13
- export declare function _memoFn<T extends (...args: any[]) => any>(fn: T, opt?: MemoOptions): T & MemoizedFunction;
14
+ export declare function _memoFn<T extends AnyFunction>(fn: T, opt?: MemoOptions<T>): T & MemoizedFunction;
@@ -1,3 +1,4 @@
1
+ import { AnyAsyncFunction } from '../types';
1
2
  import type { AsyncMemoOptions } from './asyncMemo.decorator';
2
3
  import type { AsyncMemoCache } from './memo.util';
3
4
  export interface MemoizedAsyncFunction {
@@ -6,4 +7,4 @@ export interface MemoizedAsyncFunction {
6
7
  /**
7
8
  * @experimental
8
9
  */
9
- export declare function _memoFnAsync<T extends (...args: any[]) => Promise<any>>(fn: T, opt: AsyncMemoOptions): T & MemoizedAsyncFunction;
10
+ export declare function _memoFnAsync<T extends AnyAsyncFunction>(fn: T, opt: AsyncMemoOptions<T>): T & MemoizedAsyncFunction;
package/dist/types.d.ts CHANGED
@@ -97,6 +97,10 @@ export type LazyPromise<T> = () => Promise<T>;
97
97
  * A function that lazily calculates something async, that can return null.
98
98
  */
99
99
  export type LazyNullablePromise<T> = () => Promise<T | null>;
100
+ /**
101
+ * Evaluates to the parameters if T is a function, otherwise never
102
+ */
103
+ export type MaybeParameters<T> = T extends AnyFunction ? Parameters<T> : never;
100
104
  /**
101
105
  * Symbol to indicate END of Sequence.
102
106
  */
@@ -295,7 +295,7 @@ export function _difference(a1, a2) {
295
295
  export function _sum(items) {
296
296
  let sum = 0;
297
297
  for (const n of items) {
298
- sum += n;
298
+ sum = (sum + n);
299
299
  }
300
300
  return sum;
301
301
  }
@@ -306,7 +306,7 @@ export function _sumBy(items, mapper) {
306
306
  const v = mapper(n, i++);
307
307
  if (typeof v === 'number') {
308
308
  // count only numbers, nothing else
309
- sum += v;
309
+ sum = (sum + v);
310
310
  }
311
311
  }
312
312
  return sum;
@@ -1,5 +1,5 @@
1
- import { _assert } from '../error/assert';
2
- import { _objectAssign, MISS } from '../types';
1
+ import { _assert, _assertTypeOf } from '../error/assert';
2
+ import { _objectAssign, MISS, } from '../types';
3
3
  import { _getTargetMethodSignature } from './decorator.util';
4
4
  import { jsonMemoSerializer } from './memo.util';
5
5
  /**
@@ -12,9 +12,7 @@ import { jsonMemoSerializer } from './memo.util';
12
12
  */
13
13
  // eslint-disable-next-line @typescript-eslint/naming-convention
14
14
  export const _AsyncMemo = (opt) => (target, key, descriptor) => {
15
- if (typeof descriptor.value !== 'function') {
16
- throw new TypeError('Memoization can be applied only to methods');
17
- }
15
+ _assertTypeOf(descriptor.value, 'function', 'Memoization can be applied only to methods');
18
16
  const originalFn = descriptor.value;
19
17
  // Map from "instance" of the Class where @_AsyncMemo is applied to AsyncMemoCache instance.
20
18
  const instanceCache = new Map();
@@ -1,4 +1,4 @@
1
- import { _assert } from '../error/assert';
1
+ import { _assert, _assertTypeOf } from '../error/assert';
2
2
  import { _objectAssign } from '../types';
3
3
  import { _getTargetMethodSignature } from './decorator.util';
4
4
  import { jsonMemoSerializer, MapMemoCache } from './memo.util';
@@ -24,9 +24,7 @@ import { jsonMemoSerializer, MapMemoCache } from './memo.util';
24
24
  */
25
25
  // eslint-disable-next-line @typescript-eslint/naming-convention
26
26
  export const _Memo = (opt = {}) => (target, key, descriptor) => {
27
- if (typeof descriptor.value !== 'function') {
28
- throw new TypeError('Memoization can be applied only to methods');
29
- }
27
+ _assertTypeOf(descriptor.value, 'function', 'Memoization can be applied only to methods');
30
28
  const originalFn = descriptor.value;
31
29
  // Map<ctx => MemoCache<cacheKey, result>>
32
30
  //
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
- "version": "14.267.2",
3
+ "version": "14.269.0",
4
4
  "scripts": {
5
5
  "prepare": "husky",
6
6
  "build": "dev-lib build-esm-cjs",
@@ -347,23 +347,26 @@ export function _difference<T>(a1: T[], a2: T[] | Set<T>): T[] {
347
347
  /**
348
348
  * Returns the sum of items, or 0 for empty array.
349
349
  */
350
- export function _sum(items: Iterable<number>): number {
351
- let sum = 0
350
+ export function _sum<N extends number>(items: Iterable<N>): N {
351
+ let sum = 0 as N
352
352
  for (const n of items) {
353
- sum += n
353
+ sum = (sum + n) as N
354
354
  }
355
355
  return sum
356
356
  }
357
357
 
358
- export function _sumBy<T>(items: Iterable<T>, mapper: Mapper<T, number | undefined>): number {
359
- let sum = 0
358
+ export function _sumBy<T, N extends number>(
359
+ items: Iterable<T>,
360
+ mapper: Mapper<T, N | undefined>,
361
+ ): N {
362
+ let sum = 0 as N
360
363
  let i = 0
361
364
 
362
365
  for (const n of items) {
363
366
  const v = mapper(n, i++)
364
367
  if (typeof v === 'number') {
365
368
  // count only numbers, nothing else
366
- sum += v
369
+ sum = (sum + v) as N
367
370
  }
368
371
  }
369
372
 
@@ -1,10 +1,17 @@
1
- import { _assert } from '../error/assert'
1
+ import { _assert, _assertTypeOf } from '../error/assert'
2
2
  import type { CommonLogger } from '../log/commonLogger'
3
- import { _objectAssign, AnyAsyncFunction, AnyFunction, AnyObject, MISS } from '../types'
3
+ import {
4
+ _objectAssign,
5
+ AnyAsyncFunction,
6
+ AnyFunction,
7
+ AnyObject,
8
+ MaybeParameters,
9
+ MISS,
10
+ } from '../types'
4
11
  import { _getTargetMethodSignature } from './decorator.util'
5
- import { AsyncMemoCache, jsonMemoSerializer } from './memo.util'
12
+ import { AsyncMemoCache, jsonMemoSerializer, MethodDecorator } from './memo.util'
6
13
 
7
- export interface AsyncMemoOptions {
14
+ export interface AsyncMemoOptions<T> {
8
15
  /**
9
16
  * Provide a custom implementation of AsyncMemoCache.
10
17
  * Function that creates an instance of `AsyncMemoCache`.
@@ -14,7 +21,7 @@ export interface AsyncMemoOptions {
14
21
  /**
15
22
  * Provide a custom implementation of CacheKey function.
16
23
  */
17
- cacheKeyFn?: (args: any[]) => any
24
+ cacheKeyFn?: (args: MaybeParameters<T>) => any
18
25
 
19
26
  /**
20
27
  * Default to `console`
@@ -43,11 +50,13 @@ export interface AsyncMemoInstance {
43
50
  */
44
51
  // eslint-disable-next-line @typescript-eslint/naming-convention
45
52
  export const _AsyncMemo =
46
- (opt: AsyncMemoOptions): MethodDecorator =>
53
+ <T>(opt: AsyncMemoOptions<T>): MethodDecorator<T> =>
47
54
  (target, key, descriptor) => {
48
- if (typeof descriptor.value !== 'function') {
49
- throw new TypeError('Memoization can be applied only to methods')
50
- }
55
+ _assertTypeOf<AnyFunction>(
56
+ descriptor.value,
57
+ 'function',
58
+ 'Memoization can be applied only to methods',
59
+ )
51
60
 
52
61
  const originalFn = descriptor.value
53
62
 
@@ -66,7 +75,7 @@ export const _AsyncMemo =
66
75
  const methodSignature = _getTargetMethodSignature(target, keyStr)
67
76
 
68
77
  // eslint-disable-next-line @typescript-eslint/promise-function-async
69
- descriptor.value = function (this: typeof target, ...args: any[]): Promise<any> {
78
+ descriptor.value = function (this: typeof target, ...args: MaybeParameters<T>): Promise<any> {
70
79
  const ctx = this
71
80
  const cacheKey = cacheKeyFn(args)
72
81
 
@@ -1,11 +1,11 @@
1
- import { _assert } from '../error/assert'
1
+ import { _assert, _assertTypeOf } from '../error/assert'
2
2
  import type { CommonLogger } from '../log/commonLogger'
3
- import { _objectAssign, AnyFunction, AnyObject } from '../types'
3
+ import { _objectAssign, AnyFunction, AnyObject, MaybeParameters } from '../types'
4
4
  import { _getTargetMethodSignature } from './decorator.util'
5
5
  import type { MemoCache } from './memo.util'
6
- import { jsonMemoSerializer, MapMemoCache } from './memo.util'
6
+ import { jsonMemoSerializer, MapMemoCache, MethodDecorator } from './memo.util'
7
7
 
8
- export interface MemoOptions {
8
+ export interface MemoOptions<T> {
9
9
  /**
10
10
  * Provide a custom implementation of MemoCache.
11
11
  * Function that creates an instance of `MemoCache`.
@@ -16,7 +16,7 @@ export interface MemoOptions {
16
16
  /**
17
17
  * Provide a custom implementation of CacheKey function.
18
18
  */
19
- cacheKeyFn?: (args: any[]) => any
19
+ cacheKeyFn?: (args: MaybeParameters<T>) => any
20
20
 
21
21
  /**
22
22
  * Default to `console`
@@ -57,11 +57,13 @@ export interface MemoInstance {
57
57
  */
58
58
  // eslint-disable-next-line @typescript-eslint/naming-convention
59
59
  export const _Memo =
60
- (opt: MemoOptions = {}): MethodDecorator =>
60
+ <T>(opt: MemoOptions<T> = {}): MethodDecorator<T> =>
61
61
  (target, key, descriptor) => {
62
- if (typeof descriptor.value !== 'function') {
63
- throw new TypeError('Memoization can be applied only to methods')
64
- }
62
+ _assertTypeOf<AnyFunction>(
63
+ descriptor.value,
64
+ 'function',
65
+ 'Memoization can be applied only to methods',
66
+ )
65
67
 
66
68
  const originalFn = descriptor.value
67
69
 
@@ -83,7 +85,7 @@ export const _Memo =
83
85
  const keyStr = String(key)
84
86
  const methodSignature = _getTargetMethodSignature(target, keyStr)
85
87
 
86
- descriptor.value = function (this: typeof target, ...args: any[]): any {
88
+ descriptor.value = function (this: typeof target, ...args: MaybeParameters<T>): any {
87
89
  const ctx = this
88
90
  const cacheKey = cacheKeyFn(args)
89
91
 
@@ -1,6 +1,6 @@
1
1
  import { _isPrimitive } from '../is.util'
2
2
  import { pDelay } from '../promise/pDelay'
3
- import type { UnixTimestamp } from '../types'
3
+ import type { AnyObject, UnixTimestamp } from '../types'
4
4
  import { MISS } from '../types'
5
5
 
6
6
  export type MemoSerializer = (args: any[]) => any
@@ -147,3 +147,14 @@ export class MapAsyncMemoCache<KEY = any, VALUE = any> implements AsyncMemoCache
147
147
  this.m.clear()
148
148
  }
149
149
  }
150
+
151
+ /**
152
+ * Generic override of Typescript's built in legacy MethodDecorator, that
153
+ * allows us to infer the parameters of the decorated method from the parameters
154
+ * of a decorator.
155
+ */
156
+ export type MethodDecorator<T> = (
157
+ target: AnyObject,
158
+ propertyKey: string | symbol,
159
+ descriptor: TypedPropertyDescriptor<T>,
160
+ ) => TypedPropertyDescriptor<T> | undefined
@@ -1,3 +1,4 @@
1
+ import { AnyFunction, MaybeParameters } from '../types'
1
2
  import type { MemoOptions } from './memo.decorator'
2
3
  import type { MemoCache } from './memo.util'
3
4
  import { jsonMemoSerializer, MapMemoCache } from './memo.util'
@@ -13,9 +14,9 @@ export interface MemoizedFunction {
13
14
  *
14
15
  * @experimental
15
16
  */
16
- export function _memoFn<T extends (...args: any[]) => any>(
17
+ export function _memoFn<T extends AnyFunction>(
17
18
  fn: T,
18
- opt: MemoOptions = {},
19
+ opt: MemoOptions<T> = {},
19
20
  ): T & MemoizedFunction {
20
21
  const {
21
22
  logger = console,
@@ -25,7 +26,7 @@ export function _memoFn<T extends (...args: any[]) => any>(
25
26
 
26
27
  const cache = cacheFactory()
27
28
 
28
- const memoizedFn = function (this: any, ...args: any[]): T {
29
+ const memoizedFn = function (this: any, ...args: MaybeParameters<T>): T {
29
30
  const ctx = this
30
31
  const cacheKey = cacheKeyFn(args)
31
32
 
@@ -1,4 +1,4 @@
1
- import { MISS } from '../types'
1
+ import { AnyAsyncFunction, MaybeParameters, MISS } from '../types'
2
2
  import type { AsyncMemoOptions } from './asyncMemo.decorator'
3
3
  import type { AsyncMemoCache } from './memo.util'
4
4
  import { jsonMemoSerializer, MapMemoCache } from './memo.util'
@@ -10,9 +10,9 @@ export interface MemoizedAsyncFunction {
10
10
  /**
11
11
  * @experimental
12
12
  */
13
- export function _memoFnAsync<T extends (...args: any[]) => Promise<any>>(
13
+ export function _memoFnAsync<T extends AnyAsyncFunction>(
14
14
  fn: T,
15
- opt: AsyncMemoOptions,
15
+ opt: AsyncMemoOptions<T>,
16
16
  ): T & MemoizedAsyncFunction {
17
17
  const {
18
18
  logger = console,
@@ -22,7 +22,7 @@ export function _memoFnAsync<T extends (...args: any[]) => Promise<any>>(
22
22
 
23
23
  const cache = cacheFactory()
24
24
 
25
- const memoizedFn = async function (this: any, ...args: any[]): Promise<any> {
25
+ const memoizedFn = async function (this: any, ...args: MaybeParameters<T>): Promise<any> {
26
26
  const ctx = this
27
27
  const cacheKey = cacheKeyFn(args)
28
28
  let value: any
package/src/types.ts CHANGED
@@ -119,6 +119,10 @@ export type LazyPromise<T> = () => Promise<T>
119
119
  * A function that lazily calculates something async, that can return null.
120
120
  */
121
121
  export type LazyNullablePromise<T> = () => Promise<T | null>
122
+ /**
123
+ * Evaluates to the parameters if T is a function, otherwise never
124
+ */
125
+ export type MaybeParameters<T> = T extends AnyFunction ? Parameters<T> : never
122
126
 
123
127
  /**
124
128
  * Symbol to indicate END of Sequence.