utilitish 0.0.4 → 0.0.5
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/array/array-constructor.d.ts +79 -12
- package/dist/array/array-constructor.js +32 -17
- package/dist/map/map-prototype.d.ts +1 -1
- package/dist/map/map-prototype.js +8 -1
- package/dist/utils.d.ts +23 -0
- package/dist/utils.js +35 -1
- package/package.json +4 -2
|
@@ -2,25 +2,92 @@ export {};
|
|
|
2
2
|
declare global {
|
|
3
3
|
interface ArrayConstructor {
|
|
4
4
|
/**
|
|
5
|
-
* Combines multiple arrays element-wise,
|
|
6
|
-
*
|
|
7
|
-
* @
|
|
5
|
+
* Combines multiple arrays element-wise, similar to Python's `itertools.zip_longest`.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* Array.zip([1, 2], ['a', 'b', 'c']);
|
|
9
|
+
* // => [[1, 'a'], [2, 'b'], [undefined, 'c']]
|
|
10
|
+
*
|
|
11
|
+
* @template T Type of the array elements
|
|
12
|
+
* @param {...T[][]} arrays Arrays to zip together
|
|
13
|
+
* @returns {Array<(T | undefined)[]>} A new array where each element is an array containing the elements at the same index from each input array. Missing elements are `undefined`.
|
|
8
14
|
*/
|
|
9
15
|
zip(...arrays: any[][]): any[][];
|
|
10
16
|
/**
|
|
11
|
-
* Generates a sequence of numbers, similar to Python's range
|
|
12
|
-
*
|
|
13
|
-
* @
|
|
14
|
-
*
|
|
15
|
-
*
|
|
17
|
+
* Generates a sequence of numbers, similar to Python's `range`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* Array.range(5);
|
|
21
|
+
* // => [0, 1, 2, 3, 4]
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* Array.range(2, 10, 2);
|
|
25
|
+
* // => [2, 4, 6, 8]
|
|
26
|
+
*
|
|
27
|
+
* @param {number} start First number, or the length if `end` is not provided
|
|
28
|
+
* @param {number} [end] Last number (excluded)
|
|
29
|
+
* @param {number} [step=1] Step between numbers (can be negative)
|
|
30
|
+
* @returns {number[]} An array containing the generated sequence
|
|
16
31
|
*/
|
|
17
32
|
range(start: number, end?: number, step?: number): number[];
|
|
18
33
|
/**
|
|
19
|
-
* Creates an array filled with the same value or
|
|
20
|
-
*
|
|
21
|
-
* @
|
|
22
|
-
*
|
|
34
|
+
* Creates an array filled with the same value or with values generated by a factory function.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* Array.repeat(3, 'x');
|
|
38
|
+
* // => ['x', 'x', 'x']
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* Array.repeat(3, () => Math.random());
|
|
42
|
+
* // => [0.12, 0.45, 0.78] (values will differ)
|
|
43
|
+
*
|
|
44
|
+
* @template T Type of the array elements
|
|
45
|
+
* @param {number} length Length of the array (must be a non-negative integer)
|
|
46
|
+
* @param {T | (() => T)} value Value or function generating the value
|
|
47
|
+
* @returns {T[]} The filled array
|
|
23
48
|
*/
|
|
24
49
|
repeat<T>(length: number, value: T | (() => T)): T[];
|
|
50
|
+
/**
|
|
51
|
+
* Creates an array filled with a given value or generated using a factory function.
|
|
52
|
+
* Supports creating multi-dimensional arrays by passing multiple sizes.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* // 1D array with primitive values
|
|
56
|
+
* Array.create('x', 5);
|
|
57
|
+
* // => ['x', 'x', 'x', 'x', 'x']
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* // 1D array with random numbers
|
|
61
|
+
* Array.create(() => Math.random(), 5);
|
|
62
|
+
* // => [0.12, 0.87, 0.45, 0.76, 0.33] (values will differ)
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* // 2D array (matrix)
|
|
66
|
+
* Array.create(0, 2, 3);
|
|
67
|
+
* // => [[0, 0, 0], [0, 0, 0]]
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* // 2D array with distinct objects
|
|
71
|
+
* Array.create(() => ({ id: 0 }), 2, 3);
|
|
72
|
+
* // => [
|
|
73
|
+
* // [{id:0}, {id:0}, {id:0}],
|
|
74
|
+
* // [{id:0}, {id:0}, {id:0}]
|
|
75
|
+
* // ]
|
|
76
|
+
*
|
|
77
|
+
* @notes
|
|
78
|
+
* - If `sizes.length === 0`, returns `[]`.
|
|
79
|
+
* - If `valueOrFactory` is a primitive, all cells contain the same value.
|
|
80
|
+
* - If `valueOrFactory` is a function, it is called for each cell to produce a fresh value.
|
|
81
|
+
* - `sizes` should be integers >= 0; negative or non-integer values are not supported.
|
|
82
|
+
*
|
|
83
|
+
* @template T
|
|
84
|
+
* @param {T | (() => T)} valueOrFactory The value to fill the array with, or a factory function producing values.
|
|
85
|
+
* @param {...number} sizes Sizes for each dimension (1D => one number, 2D => two numbers, etc.).
|
|
86
|
+
* @returns {any[]} A multi-dimensional array of depth `sizes.length` filled with values from `valueOrFactory`.
|
|
87
|
+
*
|
|
88
|
+
* @remarks
|
|
89
|
+
* - This method is **static** and must be called on `Array`, not on an instance.
|
|
90
|
+
*/
|
|
91
|
+
create<T>(valueOrFactory: T | (() => T), ...sizes: number[]): any[];
|
|
25
92
|
}
|
|
26
93
|
}
|
|
@@ -1,36 +1,51 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
3
|
+
const utils_1 = require("../utils");
|
|
4
|
+
/**
|
|
5
|
+
* @see Array.zip
|
|
6
|
+
*/
|
|
7
|
+
(0, utils_1.defineStaticIfNotExists)(Array, 'zip', function (...arrays) {
|
|
4
8
|
if (arrays.length === 0)
|
|
5
9
|
return [];
|
|
6
10
|
const maxLen = Math.max(...arrays.map((arr) => arr.length));
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Array.range = function (start, end, step = 1) {
|
|
11
|
+
return Array.from({ length: maxLen }, (_, i) => arrays.map((arr) => arr[i]));
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* @see Array.range
|
|
15
|
+
*/
|
|
16
|
+
(0, utils_1.defineStaticIfNotExists)(Array, 'range', function (start, end, step = 1) {
|
|
14
17
|
if (end === undefined) {
|
|
15
18
|
end = start;
|
|
16
19
|
start = 0;
|
|
17
20
|
}
|
|
18
|
-
const result = [];
|
|
19
21
|
if (step === 0)
|
|
20
22
|
throw new Error('step must not be 0');
|
|
23
|
+
const result = [];
|
|
21
24
|
const condition = step > 0 ? (i) => i < end : (i) => i > end;
|
|
22
25
|
for (let i = start; condition(i); i += step) {
|
|
23
26
|
result.push(i);
|
|
24
27
|
}
|
|
25
28
|
return result;
|
|
26
|
-
};
|
|
27
|
-
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* @see Array.repeat
|
|
32
|
+
*/
|
|
33
|
+
(0, utils_1.defineStaticIfNotExists)(Array, 'repeat', function (length, value) {
|
|
28
34
|
if (typeof length !== 'number' || !Number.isInteger(length) || length < 0) {
|
|
29
|
-
throw new TypeError('
|
|
35
|
+
throw new TypeError('Length must be a non-negative integer');
|
|
30
36
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
return Array.from({ length }, () => (typeof value === 'function' ? value() : value));
|
|
38
|
+
});
|
|
39
|
+
/**
|
|
40
|
+
* @see Array.create
|
|
41
|
+
*/
|
|
42
|
+
(0, utils_1.defineStaticIfNotExists)(Array, 'create', function (valueOrFactory, ...sizes) {
|
|
43
|
+
if (sizes.length === 0)
|
|
44
|
+
return [];
|
|
45
|
+
if (!sizes.every((s) => Number.isInteger(s) && s >= 0)) {
|
|
46
|
+
throw new TypeError('All sizes must be non-negative integers');
|
|
34
47
|
}
|
|
35
|
-
|
|
36
|
-
};
|
|
48
|
+
const getValue = typeof valueOrFactory === 'function' ? valueOrFactory : () => valueOrFactory;
|
|
49
|
+
const createDimension = (dimIndex) => Array.from({ length: sizes[dimIndex] }, () => dimIndex === sizes.length - 1 ? getValue() : createDimension(dimIndex + 1));
|
|
50
|
+
return createDimension(0);
|
|
51
|
+
});
|
|
@@ -27,8 +27,15 @@ const utils_1 = require("../utils");
|
|
|
27
27
|
}
|
|
28
28
|
});
|
|
29
29
|
(0, utils_1.defineIfNotExists)(Map.prototype, 'ensureArray', function (key) {
|
|
30
|
+
if (key === null || key === undefined) {
|
|
31
|
+
throw new TypeError('Key cannot be null or undefined');
|
|
32
|
+
}
|
|
30
33
|
if (!this.has(key)) {
|
|
31
34
|
this.set(key, []);
|
|
32
35
|
}
|
|
33
|
-
|
|
36
|
+
const arr = this.get(key);
|
|
37
|
+
if (!Array.isArray(arr)) {
|
|
38
|
+
throw new TypeError('Value for the key is not an array');
|
|
39
|
+
}
|
|
40
|
+
return arr;
|
|
34
41
|
});
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
export declare const defineIfNotExists: <T extends object>(prototype: T, name: string, fn: Function) => void;
|
|
2
|
+
/**
|
|
3
|
+
* Defines a **static** property on a constructor if it does not already exist
|
|
4
|
+
* (or if the existing property is writable **or** configurable).
|
|
5
|
+
*
|
|
6
|
+
* - Does **not** affect instance prototypes (use `defineIfNotExists` for `Foo.prototype`).
|
|
7
|
+
* - The property is created with: { enumerable: false, configurable: false, writable: false }
|
|
8
|
+
* making it non-enumerable and immutable after definition.
|
|
9
|
+
* - If an existing property is non-configurable AND non-writable, it will **not** be replaced.
|
|
10
|
+
*
|
|
11
|
+
* @template T
|
|
12
|
+
* @param {T} constructor The constructor object (e.g., `Array`, `String`, `Map`, ...)
|
|
13
|
+
* @param {string} name The name of the static method to define (e.g., `'create'`, `'range'`)
|
|
14
|
+
* @param {Function} fn The function to attach as a static property
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Define Array.range if possible
|
|
18
|
+
* defineStaticIfNotExists(Array, 'range', function(start: number, end?: number) { ... });
|
|
19
|
+
*
|
|
20
|
+
* @remarks
|
|
21
|
+
* - To force replacement, delete the property first or use Object.defineProperty directly.
|
|
22
|
+
* - This function is meant to standardize the addition of static methods in utilitish.
|
|
23
|
+
*/
|
|
24
|
+
export declare const defineStaticIfNotExists: <T extends object>(constructor: T, name: string, fn: Function) => void;
|
|
2
25
|
export declare function resolveSelector<T, R>(selector?: keyof T | ((item: T) => R), fallback?: (item: T, index?: number) => R, name?: string): (item: T, index?: number) => R;
|
|
3
26
|
export declare function assertValidSelector<T, R>(selector: any, name?: string): asserts selector is Selector<T, R>;
|
|
4
27
|
export declare function isNumberOrString(value: unknown): value is string | number;
|
package/dist/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.defineIfNotExists = void 0;
|
|
3
|
+
exports.defineStaticIfNotExists = exports.defineIfNotExists = void 0;
|
|
4
4
|
exports.resolveSelector = resolveSelector;
|
|
5
5
|
exports.assertValidSelector = assertValidSelector;
|
|
6
6
|
exports.isNumberOrString = isNumberOrString;
|
|
@@ -16,6 +16,40 @@ const defineIfNotExists = (prototype, name, fn) => {
|
|
|
16
16
|
}
|
|
17
17
|
};
|
|
18
18
|
exports.defineIfNotExists = defineIfNotExists;
|
|
19
|
+
/**
|
|
20
|
+
* Defines a **static** property on a constructor if it does not already exist
|
|
21
|
+
* (or if the existing property is writable **or** configurable).
|
|
22
|
+
*
|
|
23
|
+
* - Does **not** affect instance prototypes (use `defineIfNotExists` for `Foo.prototype`).
|
|
24
|
+
* - The property is created with: { enumerable: false, configurable: false, writable: false }
|
|
25
|
+
* making it non-enumerable and immutable after definition.
|
|
26
|
+
* - If an existing property is non-configurable AND non-writable, it will **not** be replaced.
|
|
27
|
+
*
|
|
28
|
+
* @template T
|
|
29
|
+
* @param {T} constructor The constructor object (e.g., `Array`, `String`, `Map`, ...)
|
|
30
|
+
* @param {string} name The name of the static method to define (e.g., `'create'`, `'range'`)
|
|
31
|
+
* @param {Function} fn The function to attach as a static property
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // Define Array.range if possible
|
|
35
|
+
* defineStaticIfNotExists(Array, 'range', function(start: number, end?: number) { ... });
|
|
36
|
+
*
|
|
37
|
+
* @remarks
|
|
38
|
+
* - To force replacement, delete the property first or use Object.defineProperty directly.
|
|
39
|
+
* - This function is meant to standardize the addition of static methods in utilitish.
|
|
40
|
+
*/
|
|
41
|
+
const defineStaticIfNotExists = (constructor, name, fn) => {
|
|
42
|
+
const descriptor = Object.getOwnPropertyDescriptor(constructor, name);
|
|
43
|
+
if (!descriptor || descriptor.writable || descriptor.configurable) {
|
|
44
|
+
Object.defineProperty(constructor, name, {
|
|
45
|
+
value: fn,
|
|
46
|
+
enumerable: false,
|
|
47
|
+
configurable: false,
|
|
48
|
+
writable: false,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
exports.defineStaticIfNotExists = defineStaticIfNotExists;
|
|
19
53
|
function resolveSelector(selector, fallback, name = 'selector') {
|
|
20
54
|
assertValidSelector(selector);
|
|
21
55
|
if (typeof selector === 'function') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "utilitish",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
],
|
|
10
10
|
"scripts": {
|
|
11
11
|
"build": "tsc",
|
|
12
|
-
"test": "jest"
|
|
12
|
+
"test": "jest",
|
|
13
|
+
"docs": "typedoc"
|
|
13
14
|
},
|
|
14
15
|
"keywords": [
|
|
15
16
|
"typescript",
|
|
@@ -22,6 +23,7 @@
|
|
|
22
23
|
"@types/jest": "^29.5.14",
|
|
23
24
|
"jest": "^29.7.0",
|
|
24
25
|
"ts-jest": "^29.3.4",
|
|
26
|
+
"typedoc": "^0.28.10",
|
|
25
27
|
"typescript": "^5.8.3"
|
|
26
28
|
}
|
|
27
29
|
}
|