ts-data-forge 1.0.0 → 1.0.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/README.md +1 -1
- package/dist/array/array-utils.d.mts +2617 -0
- package/dist/array/array-utils.d.mts.map +1 -0
- package/dist/array/array-utils.mjs +2915 -0
- package/dist/array/array-utils.mjs.map +1 -0
- package/dist/array/index.d.mts +3 -0
- package/dist/array/index.d.mts.map +1 -0
- package/dist/array/index.mjs +3 -0
- package/dist/array/index.mjs.map +1 -0
- package/dist/array/tuple-utils.d.mts +421 -0
- package/dist/array/tuple-utils.d.mts.map +1 -0
- package/dist/array/tuple-utils.mjs +391 -0
- package/dist/array/tuple-utils.mjs.map +1 -0
- package/dist/collections/imap-mapped.d.mts +445 -0
- package/dist/collections/imap-mapped.d.mts.map +1 -0
- package/dist/collections/imap-mapped.mjs +424 -0
- package/dist/collections/imap-mapped.mjs.map +1 -0
- package/dist/collections/imap.d.mts +359 -0
- package/dist/collections/imap.d.mts.map +1 -0
- package/dist/collections/imap.mjs +338 -0
- package/dist/collections/imap.mjs.map +1 -0
- package/dist/collections/index.d.mts +7 -0
- package/dist/collections/index.d.mts.map +1 -0
- package/dist/collections/index.mjs +7 -0
- package/dist/collections/index.mjs.map +1 -0
- package/dist/collections/iset-mapped.d.mts +576 -0
- package/dist/collections/iset-mapped.d.mts.map +1 -0
- package/dist/collections/iset-mapped.mjs +522 -0
- package/dist/collections/iset-mapped.mjs.map +1 -0
- package/dist/collections/iset.d.mts +426 -0
- package/dist/collections/iset.d.mts.map +1 -0
- package/dist/collections/iset.mjs +437 -0
- package/dist/collections/iset.mjs.map +1 -0
- package/dist/collections/queue.d.mts +190 -0
- package/dist/collections/queue.d.mts.map +1 -0
- package/dist/collections/queue.mjs +317 -0
- package/dist/collections/queue.mjs.map +1 -0
- package/dist/collections/stack.d.mts +210 -0
- package/dist/collections/stack.d.mts.map +1 -0
- package/dist/collections/stack.mjs +353 -0
- package/dist/collections/stack.mjs.map +1 -0
- package/dist/expect-type.d.mts +199 -0
- package/dist/expect-type.d.mts.map +1 -0
- package/dist/expect-type.mjs +201 -0
- package/dist/expect-type.mjs.map +1 -0
- package/dist/functional/index.d.mts +5 -0
- package/dist/functional/index.d.mts.map +1 -0
- package/dist/functional/index.mjs +5 -0
- package/dist/functional/index.mjs.map +1 -0
- package/dist/functional/match.d.mts +215 -0
- package/dist/functional/match.d.mts.map +1 -0
- package/dist/functional/match.mjs +139 -0
- package/dist/functional/match.mjs.map +1 -0
- package/dist/functional/optional.d.mts +517 -0
- package/dist/functional/optional.d.mts.map +1 -0
- package/dist/functional/optional.mjs +532 -0
- package/dist/functional/optional.mjs.map +1 -0
- package/dist/functional/pipe.d.mts +185 -0
- package/dist/functional/pipe.d.mts.map +1 -0
- package/dist/functional/pipe.mjs +129 -0
- package/dist/functional/pipe.mjs.map +1 -0
- package/dist/functional/result.d.mts +796 -0
- package/dist/functional/result.d.mts.map +1 -0
- package/dist/functional/result.mjs +844 -0
- package/dist/functional/result.mjs.map +1 -0
- package/dist/globals.d.mts +38 -0
- package/dist/guard/has-key.d.mts +100 -0
- package/dist/guard/has-key.d.mts.map +1 -0
- package/dist/guard/has-key.mjs +94 -0
- package/dist/guard/has-key.mjs.map +1 -0
- package/dist/guard/index.d.mts +8 -0
- package/dist/guard/index.d.mts.map +1 -0
- package/dist/guard/index.mjs +8 -0
- package/dist/guard/index.mjs.map +1 -0
- package/dist/guard/is-non-empty-string.d.mts +106 -0
- package/dist/guard/is-non-empty-string.d.mts.map +1 -0
- package/dist/guard/is-non-empty-string.mjs +108 -0
- package/dist/guard/is-non-empty-string.mjs.map +1 -0
- package/dist/guard/is-non-null-object.d.mts +105 -0
- package/dist/guard/is-non-null-object.d.mts.map +1 -0
- package/dist/guard/is-non-null-object.mjs +108 -0
- package/dist/guard/is-non-null-object.mjs.map +1 -0
- package/dist/guard/is-primitive.d.mts +146 -0
- package/dist/guard/is-primitive.d.mts.map +1 -0
- package/dist/guard/is-primitive.mjs +161 -0
- package/dist/guard/is-primitive.mjs.map +1 -0
- package/dist/guard/is-record.d.mts +151 -0
- package/dist/guard/is-record.d.mts.map +1 -0
- package/dist/guard/is-record.mjs +155 -0
- package/dist/guard/is-record.mjs.map +1 -0
- package/dist/guard/is-type.d.mts +430 -0
- package/dist/guard/is-type.d.mts.map +1 -0
- package/dist/guard/is-type.mjs +432 -0
- package/dist/guard/is-type.mjs.map +1 -0
- package/dist/guard/key-is-in.d.mts +158 -0
- package/dist/guard/key-is-in.d.mts.map +1 -0
- package/dist/guard/key-is-in.mjs +160 -0
- package/dist/guard/key-is-in.mjs.map +1 -0
- package/dist/index.d.mts +11 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +61 -0
- package/dist/index.mjs.map +1 -0
- package/dist/iterator/index.d.mts +2 -0
- package/dist/iterator/index.d.mts.map +1 -0
- package/dist/iterator/index.mjs +2 -0
- package/dist/iterator/index.mjs.map +1 -0
- package/dist/iterator/range.d.mts +97 -0
- package/dist/iterator/range.d.mts.map +1 -0
- package/dist/iterator/range.mjs +130 -0
- package/dist/iterator/range.mjs.map +1 -0
- package/dist/json/index.d.mts +2 -0
- package/dist/json/index.d.mts.map +1 -0
- package/dist/json/index.mjs +2 -0
- package/dist/json/index.mjs.map +1 -0
- package/dist/json/json.d.mts +597 -0
- package/dist/json/json.d.mts.map +1 -0
- package/dist/json/json.mjs +687 -0
- package/dist/json/json.mjs.map +1 -0
- package/dist/number/branded-types/finite-number.d.mts +291 -0
- package/dist/number/branded-types/finite-number.d.mts.map +1 -0
- package/dist/number/branded-types/finite-number.mjs +296 -0
- package/dist/number/branded-types/finite-number.mjs.map +1 -0
- package/dist/number/branded-types/index.d.mts +27 -0
- package/dist/number/branded-types/index.d.mts.map +1 -0
- package/dist/number/branded-types/index.mjs +27 -0
- package/dist/number/branded-types/index.mjs.map +1 -0
- package/dist/number/branded-types/int.d.mts +242 -0
- package/dist/number/branded-types/int.d.mts.map +1 -0
- package/dist/number/branded-types/int.mjs +239 -0
- package/dist/number/branded-types/int.mjs.map +1 -0
- package/dist/number/branded-types/int16.d.mts +162 -0
- package/dist/number/branded-types/int16.d.mts.map +1 -0
- package/dist/number/branded-types/int16.mjs +141 -0
- package/dist/number/branded-types/int16.mjs.map +1 -0
- package/dist/number/branded-types/int32.d.mts +155 -0
- package/dist/number/branded-types/int32.d.mts.map +1 -0
- package/dist/number/branded-types/int32.mjs +142 -0
- package/dist/number/branded-types/int32.mjs.map +1 -0
- package/dist/number/branded-types/non-negative-finite-number.d.mts +165 -0
- package/dist/number/branded-types/non-negative-finite-number.d.mts.map +1 -0
- package/dist/number/branded-types/non-negative-finite-number.mjs +160 -0
- package/dist/number/branded-types/non-negative-finite-number.mjs.map +1 -0
- package/dist/number/branded-types/non-negative-int16.d.mts +160 -0
- package/dist/number/branded-types/non-negative-int16.d.mts.map +1 -0
- package/dist/number/branded-types/non-negative-int16.mjs +138 -0
- package/dist/number/branded-types/non-negative-int16.mjs.map +1 -0
- package/dist/number/branded-types/non-negative-int32.d.mts +156 -0
- package/dist/number/branded-types/non-negative-int32.d.mts.map +1 -0
- package/dist/number/branded-types/non-negative-int32.mjs +138 -0
- package/dist/number/branded-types/non-negative-int32.mjs.map +1 -0
- package/dist/number/branded-types/non-zero-finite-number.d.mts +154 -0
- package/dist/number/branded-types/non-zero-finite-number.d.mts.map +1 -0
- package/dist/number/branded-types/non-zero-finite-number.mjs +160 -0
- package/dist/number/branded-types/non-zero-finite-number.mjs.map +1 -0
- package/dist/number/branded-types/non-zero-int.d.mts +131 -0
- package/dist/number/branded-types/non-zero-int.d.mts.map +1 -0
- package/dist/number/branded-types/non-zero-int.mjs +128 -0
- package/dist/number/branded-types/non-zero-int.mjs.map +1 -0
- package/dist/number/branded-types/non-zero-int16.d.mts +166 -0
- package/dist/number/branded-types/non-zero-int16.d.mts.map +1 -0
- package/dist/number/branded-types/non-zero-int16.mjs +145 -0
- package/dist/number/branded-types/non-zero-int16.mjs.map +1 -0
- package/dist/number/branded-types/non-zero-int32.d.mts +158 -0
- package/dist/number/branded-types/non-zero-int32.d.mts.map +1 -0
- package/dist/number/branded-types/non-zero-int32.mjs +145 -0
- package/dist/number/branded-types/non-zero-int32.mjs.map +1 -0
- package/dist/number/branded-types/non-zero-safe-int.d.mts +148 -0
- package/dist/number/branded-types/non-zero-safe-int.d.mts.map +1 -0
- package/dist/number/branded-types/non-zero-safe-int.mjs +145 -0
- package/dist/number/branded-types/non-zero-safe-int.mjs.map +1 -0
- package/dist/number/branded-types/non-zero-uint16.d.mts +160 -0
- package/dist/number/branded-types/non-zero-uint16.d.mts.map +1 -0
- package/dist/number/branded-types/non-zero-uint16.mjs +140 -0
- package/dist/number/branded-types/non-zero-uint16.mjs.map +1 -0
- package/dist/number/branded-types/non-zero-uint32.d.mts +156 -0
- package/dist/number/branded-types/non-zero-uint32.d.mts.map +1 -0
- package/dist/number/branded-types/non-zero-uint32.mjs +140 -0
- package/dist/number/branded-types/non-zero-uint32.mjs.map +1 -0
- package/dist/number/branded-types/positive-finite-number.d.mts +171 -0
- package/dist/number/branded-types/positive-finite-number.d.mts.map +1 -0
- package/dist/number/branded-types/positive-finite-number.mjs +165 -0
- package/dist/number/branded-types/positive-finite-number.mjs.map +1 -0
- package/dist/number/branded-types/positive-int.d.mts +270 -0
- package/dist/number/branded-types/positive-int.d.mts.map +1 -0
- package/dist/number/branded-types/positive-int.mjs +257 -0
- package/dist/number/branded-types/positive-int.mjs.map +1 -0
- package/dist/number/branded-types/positive-int16.d.mts +162 -0
- package/dist/number/branded-types/positive-int16.d.mts.map +1 -0
- package/dist/number/branded-types/positive-int16.mjs +139 -0
- package/dist/number/branded-types/positive-int16.mjs.map +1 -0
- package/dist/number/branded-types/positive-int32.d.mts +158 -0
- package/dist/number/branded-types/positive-int32.d.mts.map +1 -0
- package/dist/number/branded-types/positive-int32.mjs +139 -0
- package/dist/number/branded-types/positive-int32.mjs.map +1 -0
- package/dist/number/branded-types/positive-safe-int.d.mts +152 -0
- package/dist/number/branded-types/positive-safe-int.d.mts.map +1 -0
- package/dist/number/branded-types/positive-safe-int.mjs +138 -0
- package/dist/number/branded-types/positive-safe-int.mjs.map +1 -0
- package/dist/number/branded-types/positive-uint16.d.mts +160 -0
- package/dist/number/branded-types/positive-uint16.d.mts.map +1 -0
- package/dist/number/branded-types/positive-uint16.mjs +139 -0
- package/dist/number/branded-types/positive-uint16.mjs.map +1 -0
- package/dist/number/branded-types/positive-uint32.d.mts +156 -0
- package/dist/number/branded-types/positive-uint32.d.mts.map +1 -0
- package/dist/number/branded-types/positive-uint32.mjs +139 -0
- package/dist/number/branded-types/positive-uint32.mjs.map +1 -0
- package/dist/number/branded-types/safe-int.d.mts +243 -0
- package/dist/number/branded-types/safe-int.d.mts.map +1 -0
- package/dist/number/branded-types/safe-int.mjs +240 -0
- package/dist/number/branded-types/safe-int.mjs.map +1 -0
- package/dist/number/branded-types/safe-uint.d.mts +151 -0
- package/dist/number/branded-types/safe-uint.d.mts.map +1 -0
- package/dist/number/branded-types/safe-uint.mjs +138 -0
- package/dist/number/branded-types/safe-uint.mjs.map +1 -0
- package/dist/number/branded-types/uint.d.mts +144 -0
- package/dist/number/branded-types/uint.d.mts.map +1 -0
- package/dist/number/branded-types/uint.mjs +132 -0
- package/dist/number/branded-types/uint.mjs.map +1 -0
- package/dist/number/branded-types/uint16.d.mts +157 -0
- package/dist/number/branded-types/uint16.d.mts.map +1 -0
- package/dist/number/branded-types/uint16.mjs +137 -0
- package/dist/number/branded-types/uint16.mjs.map +1 -0
- package/dist/number/branded-types/uint32.d.mts +185 -0
- package/dist/number/branded-types/uint32.d.mts.map +1 -0
- package/dist/number/branded-types/uint32.mjs +169 -0
- package/dist/number/branded-types/uint32.mjs.map +1 -0
- package/dist/number/enum/index.d.mts +3 -0
- package/dist/number/enum/index.d.mts.map +1 -0
- package/dist/number/enum/index.mjs +3 -0
- package/dist/number/enum/index.mjs.map +1 -0
- package/dist/number/enum/int8.d.mts +202 -0
- package/dist/number/enum/int8.d.mts.map +1 -0
- package/dist/number/enum/int8.mjs +296 -0
- package/dist/number/enum/int8.mjs.map +1 -0
- package/dist/number/enum/uint8.d.mts +128 -0
- package/dist/number/enum/uint8.d.mts.map +1 -0
- package/dist/number/enum/uint8.mjs +251 -0
- package/dist/number/enum/uint8.mjs.map +1 -0
- package/dist/number/index.d.mts +5 -0
- package/dist/number/index.d.mts.map +1 -0
- package/dist/number/index.mjs +31 -0
- package/dist/number/index.mjs.map +1 -0
- package/dist/number/num.d.mts +515 -0
- package/dist/number/num.d.mts.map +1 -0
- package/dist/number/num.mjs +513 -0
- package/dist/number/num.mjs.map +1 -0
- package/dist/number/refined-number-utils.d.mts +191 -0
- package/dist/number/refined-number-utils.d.mts.map +1 -0
- package/dist/number/refined-number-utils.mjs +179 -0
- package/dist/number/refined-number-utils.mjs.map +1 -0
- package/dist/object/index.d.mts +2 -0
- package/dist/object/index.d.mts.map +1 -0
- package/dist/object/index.mjs +2 -0
- package/dist/object/index.mjs.map +1 -0
- package/dist/object/object.d.mts +296 -0
- package/dist/object/object.d.mts.map +1 -0
- package/dist/object/object.mjs +295 -0
- package/dist/object/object.mjs.map +1 -0
- package/dist/others/cast-mutable.d.mts +110 -0
- package/dist/others/cast-mutable.d.mts.map +1 -0
- package/dist/others/cast-mutable.mjs +114 -0
- package/dist/others/cast-mutable.mjs.map +1 -0
- package/dist/others/cast-readonly.d.mts +189 -0
- package/dist/others/cast-readonly.d.mts.map +1 -0
- package/dist/others/cast-readonly.mjs +193 -0
- package/dist/others/cast-readonly.mjs.map +1 -0
- package/dist/others/if-then.d.mts +98 -0
- package/dist/others/if-then.d.mts.map +1 -0
- package/dist/others/if-then.mjs +100 -0
- package/dist/others/if-then.mjs.map +1 -0
- package/dist/others/index.d.mts +8 -0
- package/dist/others/index.d.mts.map +1 -0
- package/dist/others/index.mjs +8 -0
- package/dist/others/index.mjs.map +1 -0
- package/dist/others/map-nullable.d.mts +151 -0
- package/dist/others/map-nullable.d.mts.map +1 -0
- package/dist/others/map-nullable.mjs +159 -0
- package/dist/others/map-nullable.mjs.map +1 -0
- package/dist/others/memoize-function.d.mts +173 -0
- package/dist/others/memoize-function.d.mts.map +1 -0
- package/dist/others/memoize-function.mjs +189 -0
- package/dist/others/memoize-function.mjs.map +1 -0
- package/dist/others/tuple.d.mts +159 -0
- package/dist/others/tuple.d.mts.map +1 -0
- package/dist/others/tuple.mjs +161 -0
- package/dist/others/tuple.mjs.map +1 -0
- package/dist/others/unknown-to-string.d.mts +180 -0
- package/dist/others/unknown-to-string.d.mts.map +1 -0
- package/dist/others/unknown-to-string.mjs +211 -0
- package/dist/others/unknown-to-string.mjs.map +1 -0
- package/dist/tsconfig.json +1 -0
- package/package.json +18 -16
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a memoized version of a function that caches results based on input arguments.
|
|
3
|
+
*
|
|
4
|
+
* The memoized function stores results in an internal Map and returns cached values
|
|
5
|
+
* for repeated calls with the same arguments. This can significantly improve performance
|
|
6
|
+
* for expensive computations or I/O operations.
|
|
7
|
+
*
|
|
8
|
+
* **Important considerations:**
|
|
9
|
+
* - The cache grows unbounded - consider memory implications for long-running applications
|
|
10
|
+
* - Cache keys must be primitives (string, number, boolean, symbol, null, undefined, bigint)
|
|
11
|
+
* - Object arguments require careful key generation to ensure uniqueness
|
|
12
|
+
* - Pure functions only - memoizing functions with side effects can lead to bugs
|
|
13
|
+
*
|
|
14
|
+
* @template A - The tuple type of the function arguments
|
|
15
|
+
* @template R - The return type of the function
|
|
16
|
+
* @template K - The primitive type used as the cache key (must be valid Map key)
|
|
17
|
+
* @param fn - The pure function to memoize
|
|
18
|
+
* @param argsToCacheKey - Function that converts arguments to a unique cache key
|
|
19
|
+
* @returns A memoized version of the input function with the same signature
|
|
20
|
+
*
|
|
21
|
+
* @example Basic memoization for expensive calculations
|
|
22
|
+
* ```typescript
|
|
23
|
+
* // Fibonacci calculation (exponential time complexity)
|
|
24
|
+
* const fibonacci = (n: number): number => {
|
|
25
|
+
* console.log(`Computing fib(${n})`);
|
|
26
|
+
* if (n <= 1) return n;
|
|
27
|
+
* return fibonacci(n - 1) + fibonacci(n - 2);
|
|
28
|
+
* };
|
|
29
|
+
*
|
|
30
|
+
* const memoizedFib = memoizeFunction(
|
|
31
|
+
* fibonacci,
|
|
32
|
+
* (n) => n // Number itself as key
|
|
33
|
+
* );
|
|
34
|
+
*
|
|
35
|
+
* memoizedFib(40); // Much faster than unmemoized version
|
|
36
|
+
* memoizedFib(40); // Returns instantly from cache
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @example Multi-argument functions with composite keys
|
|
40
|
+
* ```typescript
|
|
41
|
+
* // Grid calculation with x,y coordinates
|
|
42
|
+
* const calculateGridValue = (x: number, y: number, scale: number): number => {
|
|
43
|
+
* console.log(`Computing grid(${x},${y},${scale})`);
|
|
44
|
+
* // Expensive computation...
|
|
45
|
+
* return Math.sin(x * scale) * Math.cos(y * scale);
|
|
46
|
+
* };
|
|
47
|
+
*
|
|
48
|
+
* const memoizedGrid = memoizeFunction(
|
|
49
|
+
* calculateGridValue,
|
|
50
|
+
* (x, y, scale) => `${x},${y},${scale}` // String concatenation for composite key
|
|
51
|
+
* );
|
|
52
|
+
*
|
|
53
|
+
* // Alternative: Using bit manipulation for integer coordinates
|
|
54
|
+
* const memoizedGrid2 = memoizeFunction(
|
|
55
|
+
* calculateGridValue,
|
|
56
|
+
* (x, y, scale) => (x << 20) | (y << 10) | scale // Assuming small positive integers
|
|
57
|
+
* );
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @example Object arguments with selective memoization
|
|
61
|
+
* ```typescript
|
|
62
|
+
* interface User {
|
|
63
|
+
* id: number;
|
|
64
|
+
* name: string;
|
|
65
|
+
* email: string;
|
|
66
|
+
* metadata?: Record<string, unknown>;
|
|
67
|
+
* }
|
|
68
|
+
*
|
|
69
|
+
* const fetchUserPermissions = async (user: User): Promise<string[]> => {
|
|
70
|
+
* console.log(`Fetching permissions for user ${user.id}`);
|
|
71
|
+
* const response = await api.get(`/permissions/${user.id}`);
|
|
72
|
+
* return response.data;
|
|
73
|
+
* };
|
|
74
|
+
*
|
|
75
|
+
* // Memoize based only on user ID, ignoring other fields
|
|
76
|
+
* const memoizedFetchPermissions = memoizeFunction(
|
|
77
|
+
* fetchUserPermissions,
|
|
78
|
+
* (user) => user.id // Only cache by ID
|
|
79
|
+
* );
|
|
80
|
+
*
|
|
81
|
+
* // For multiple identifying fields
|
|
82
|
+
* const processUserData = (user: User, orgId: number): ProcessedData => {
|
|
83
|
+
* // Complex processing...
|
|
84
|
+
* };
|
|
85
|
+
*
|
|
86
|
+
* const memoizedProcess = memoizeFunction(
|
|
87
|
+
* processUserData,
|
|
88
|
+
* (user, orgId) => `${user.id}:${orgId}` // Composite key with separator
|
|
89
|
+
* );
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* @example Memoizing recursive functions
|
|
93
|
+
* ```typescript
|
|
94
|
+
* // Recursive path finding
|
|
95
|
+
* const findPaths = (start: string, end: string, visited: Set<string> = new Set()): string[][] => {
|
|
96
|
+
* if (start === end) return [[end]];
|
|
97
|
+
* // ... complex recursive logic
|
|
98
|
+
* };
|
|
99
|
+
*
|
|
100
|
+
* // Use sorted, serialized visited set for consistent keys
|
|
101
|
+
* const memoizedFindPaths = memoizeFunction(
|
|
102
|
+
* findPaths,
|
|
103
|
+
* (start, end, visited = new Set()) =>
|
|
104
|
+
* `${start}->${end}:[${[...visited].sort().join(',')}]`
|
|
105
|
+
* );
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @example Cache key strategies
|
|
109
|
+
* ```typescript
|
|
110
|
+
* // 1. Simple primitive argument
|
|
111
|
+
* memoizeFunction(fn, (x: number) => x);
|
|
112
|
+
*
|
|
113
|
+
* // 2. Multiple arguments with separator
|
|
114
|
+
* memoizeFunction(fn, (a: string, b: number) => `${a}|${b}`);
|
|
115
|
+
*
|
|
116
|
+
* // 3. Object with specific fields
|
|
117
|
+
* memoizeFunction(fn, (obj: { id: number; version: number }) =>
|
|
118
|
+
* `${obj.id}:v${obj.version}`
|
|
119
|
+
* );
|
|
120
|
+
*
|
|
121
|
+
* // 4. Array argument with JSON serialization
|
|
122
|
+
* memoizeFunction(fn, (arr: number[]) => JSON.stringify(arr));
|
|
123
|
+
*
|
|
124
|
+
* // 5. Boolean flags as bit field
|
|
125
|
+
* memoizeFunction(fn, (a: boolean, b: boolean, c: boolean) =>
|
|
126
|
+
* (a ? 4 : 0) | (b ? 2 : 0) | (c ? 1 : 0)
|
|
127
|
+
* );
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* @example Memory-conscious memoization with weak references
|
|
131
|
+
* ```typescript
|
|
132
|
+
* // For object keys, consider using WeakMap externally
|
|
133
|
+
* const cache = new WeakMap<object, Result>();
|
|
134
|
+
*
|
|
135
|
+
* function memoizeWithWeakMap<T extends object, R>(
|
|
136
|
+
* fn: (obj: T) => R
|
|
137
|
+
* ): (obj: T) => R {
|
|
138
|
+
* return (obj: T): R => {
|
|
139
|
+
* if (cache.has(obj)) {
|
|
140
|
+
* return cache.get(obj)!;
|
|
141
|
+
* }
|
|
142
|
+
* const result = fn(obj);
|
|
143
|
+
* cache.set(obj, result);
|
|
144
|
+
* return result;
|
|
145
|
+
* };
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* @example Anti-patterns to avoid
|
|
150
|
+
* ```typescript
|
|
151
|
+
* // ❌ Bad: Memoizing impure functions
|
|
152
|
+
* const memoizedRandom = memoizeFunction(
|
|
153
|
+
* () => Math.random(),
|
|
154
|
+
* () => 'key' // Always returns cached random value!
|
|
155
|
+
* );
|
|
156
|
+
*
|
|
157
|
+
* // ❌ Bad: Memoizing functions with side effects
|
|
158
|
+
* const memoizedLog = memoizeFunction(
|
|
159
|
+
* (msg: string) => { console.log(msg); return msg; },
|
|
160
|
+
* (msg) => msg // Logs only on first call!
|
|
161
|
+
* );
|
|
162
|
+
*
|
|
163
|
+
* // ❌ Bad: Non-unique cache keys
|
|
164
|
+
* const memoizedProcess = memoizeFunction(
|
|
165
|
+
* (user: User) => processUser(user),
|
|
166
|
+
* (user) => user.name // Multiple users can have same name!
|
|
167
|
+
* );
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* @see https://en.wikipedia.org/wiki/Memoization
|
|
171
|
+
*/
|
|
172
|
+
export declare const memoizeFunction: <const A extends readonly unknown[], R, K extends Primitive>(fn: (...args: A) => R, argsToCacheKey: (...args: A) => K) => ((...args: A) => R);
|
|
173
|
+
//# sourceMappingURL=memoize-function.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memoize-function.d.mts","sourceRoot":"","sources":["../../src/others/memoize-function.mts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0KG;AACH,eAAO,MAAM,eAAe,GAC1B,KAAK,CAAC,CAAC,SAAS,SAAS,OAAO,EAAE,EAClC,CAAC,EACD,CAAC,SAAS,SAAS,EAEnB,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,EACrB,gBAAgB,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,KAChC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,CAiBpB,CAAC"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a memoized version of a function that caches results based on input arguments.
|
|
3
|
+
*
|
|
4
|
+
* The memoized function stores results in an internal Map and returns cached values
|
|
5
|
+
* for repeated calls with the same arguments. This can significantly improve performance
|
|
6
|
+
* for expensive computations or I/O operations.
|
|
7
|
+
*
|
|
8
|
+
* **Important considerations:**
|
|
9
|
+
* - The cache grows unbounded - consider memory implications for long-running applications
|
|
10
|
+
* - Cache keys must be primitives (string, number, boolean, symbol, null, undefined, bigint)
|
|
11
|
+
* - Object arguments require careful key generation to ensure uniqueness
|
|
12
|
+
* - Pure functions only - memoizing functions with side effects can lead to bugs
|
|
13
|
+
*
|
|
14
|
+
* @template A - The tuple type of the function arguments
|
|
15
|
+
* @template R - The return type of the function
|
|
16
|
+
* @template K - The primitive type used as the cache key (must be valid Map key)
|
|
17
|
+
* @param fn - The pure function to memoize
|
|
18
|
+
* @param argsToCacheKey - Function that converts arguments to a unique cache key
|
|
19
|
+
* @returns A memoized version of the input function with the same signature
|
|
20
|
+
*
|
|
21
|
+
* @example Basic memoization for expensive calculations
|
|
22
|
+
* ```typescript
|
|
23
|
+
* // Fibonacci calculation (exponential time complexity)
|
|
24
|
+
* const fibonacci = (n: number): number => {
|
|
25
|
+
* console.log(`Computing fib(${n})`);
|
|
26
|
+
* if (n <= 1) return n;
|
|
27
|
+
* return fibonacci(n - 1) + fibonacci(n - 2);
|
|
28
|
+
* };
|
|
29
|
+
*
|
|
30
|
+
* const memoizedFib = memoizeFunction(
|
|
31
|
+
* fibonacci,
|
|
32
|
+
* (n) => n // Number itself as key
|
|
33
|
+
* );
|
|
34
|
+
*
|
|
35
|
+
* memoizedFib(40); // Much faster than unmemoized version
|
|
36
|
+
* memoizedFib(40); // Returns instantly from cache
|
|
37
|
+
* ```
|
|
38
|
+
*
|
|
39
|
+
* @example Multi-argument functions with composite keys
|
|
40
|
+
* ```typescript
|
|
41
|
+
* // Grid calculation with x,y coordinates
|
|
42
|
+
* const calculateGridValue = (x: number, y: number, scale: number): number => {
|
|
43
|
+
* console.log(`Computing grid(${x},${y},${scale})`);
|
|
44
|
+
* // Expensive computation...
|
|
45
|
+
* return Math.sin(x * scale) * Math.cos(y * scale);
|
|
46
|
+
* };
|
|
47
|
+
*
|
|
48
|
+
* const memoizedGrid = memoizeFunction(
|
|
49
|
+
* calculateGridValue,
|
|
50
|
+
* (x, y, scale) => `${x},${y},${scale}` // String concatenation for composite key
|
|
51
|
+
* );
|
|
52
|
+
*
|
|
53
|
+
* // Alternative: Using bit manipulation for integer coordinates
|
|
54
|
+
* const memoizedGrid2 = memoizeFunction(
|
|
55
|
+
* calculateGridValue,
|
|
56
|
+
* (x, y, scale) => (x << 20) | (y << 10) | scale // Assuming small positive integers
|
|
57
|
+
* );
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @example Object arguments with selective memoization
|
|
61
|
+
* ```typescript
|
|
62
|
+
* interface User {
|
|
63
|
+
* id: number;
|
|
64
|
+
* name: string;
|
|
65
|
+
* email: string;
|
|
66
|
+
* metadata?: Record<string, unknown>;
|
|
67
|
+
* }
|
|
68
|
+
*
|
|
69
|
+
* const fetchUserPermissions = async (user: User): Promise<string[]> => {
|
|
70
|
+
* console.log(`Fetching permissions for user ${user.id}`);
|
|
71
|
+
* const response = await api.get(`/permissions/${user.id}`);
|
|
72
|
+
* return response.data;
|
|
73
|
+
* };
|
|
74
|
+
*
|
|
75
|
+
* // Memoize based only on user ID, ignoring other fields
|
|
76
|
+
* const memoizedFetchPermissions = memoizeFunction(
|
|
77
|
+
* fetchUserPermissions,
|
|
78
|
+
* (user) => user.id // Only cache by ID
|
|
79
|
+
* );
|
|
80
|
+
*
|
|
81
|
+
* // For multiple identifying fields
|
|
82
|
+
* const processUserData = (user: User, orgId: number): ProcessedData => {
|
|
83
|
+
* // Complex processing...
|
|
84
|
+
* };
|
|
85
|
+
*
|
|
86
|
+
* const memoizedProcess = memoizeFunction(
|
|
87
|
+
* processUserData,
|
|
88
|
+
* (user, orgId) => `${user.id}:${orgId}` // Composite key with separator
|
|
89
|
+
* );
|
|
90
|
+
* ```
|
|
91
|
+
*
|
|
92
|
+
* @example Memoizing recursive functions
|
|
93
|
+
* ```typescript
|
|
94
|
+
* // Recursive path finding
|
|
95
|
+
* const findPaths = (start: string, end: string, visited: Set<string> = new Set()): string[][] => {
|
|
96
|
+
* if (start === end) return [[end]];
|
|
97
|
+
* // ... complex recursive logic
|
|
98
|
+
* };
|
|
99
|
+
*
|
|
100
|
+
* // Use sorted, serialized visited set for consistent keys
|
|
101
|
+
* const memoizedFindPaths = memoizeFunction(
|
|
102
|
+
* findPaths,
|
|
103
|
+
* (start, end, visited = new Set()) =>
|
|
104
|
+
* `${start}->${end}:[${[...visited].sort().join(',')}]`
|
|
105
|
+
* );
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @example Cache key strategies
|
|
109
|
+
* ```typescript
|
|
110
|
+
* // 1. Simple primitive argument
|
|
111
|
+
* memoizeFunction(fn, (x: number) => x);
|
|
112
|
+
*
|
|
113
|
+
* // 2. Multiple arguments with separator
|
|
114
|
+
* memoizeFunction(fn, (a: string, b: number) => `${a}|${b}`);
|
|
115
|
+
*
|
|
116
|
+
* // 3. Object with specific fields
|
|
117
|
+
* memoizeFunction(fn, (obj: { id: number; version: number }) =>
|
|
118
|
+
* `${obj.id}:v${obj.version}`
|
|
119
|
+
* );
|
|
120
|
+
*
|
|
121
|
+
* // 4. Array argument with JSON serialization
|
|
122
|
+
* memoizeFunction(fn, (arr: number[]) => JSON.stringify(arr));
|
|
123
|
+
*
|
|
124
|
+
* // 5. Boolean flags as bit field
|
|
125
|
+
* memoizeFunction(fn, (a: boolean, b: boolean, c: boolean) =>
|
|
126
|
+
* (a ? 4 : 0) | (b ? 2 : 0) | (c ? 1 : 0)
|
|
127
|
+
* );
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* @example Memory-conscious memoization with weak references
|
|
131
|
+
* ```typescript
|
|
132
|
+
* // For object keys, consider using WeakMap externally
|
|
133
|
+
* const cache = new WeakMap<object, Result>();
|
|
134
|
+
*
|
|
135
|
+
* function memoizeWithWeakMap<T extends object, R>(
|
|
136
|
+
* fn: (obj: T) => R
|
|
137
|
+
* ): (obj: T) => R {
|
|
138
|
+
* return (obj: T): R => {
|
|
139
|
+
* if (cache.has(obj)) {
|
|
140
|
+
* return cache.get(obj)!;
|
|
141
|
+
* }
|
|
142
|
+
* const result = fn(obj);
|
|
143
|
+
* cache.set(obj, result);
|
|
144
|
+
* return result;
|
|
145
|
+
* };
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*
|
|
149
|
+
* @example Anti-patterns to avoid
|
|
150
|
+
* ```typescript
|
|
151
|
+
* // ❌ Bad: Memoizing impure functions
|
|
152
|
+
* const memoizedRandom = memoizeFunction(
|
|
153
|
+
* () => Math.random(),
|
|
154
|
+
* () => 'key' // Always returns cached random value!
|
|
155
|
+
* );
|
|
156
|
+
*
|
|
157
|
+
* // ❌ Bad: Memoizing functions with side effects
|
|
158
|
+
* const memoizedLog = memoizeFunction(
|
|
159
|
+
* (msg: string) => { console.log(msg); return msg; },
|
|
160
|
+
* (msg) => msg // Logs only on first call!
|
|
161
|
+
* );
|
|
162
|
+
*
|
|
163
|
+
* // ❌ Bad: Non-unique cache keys
|
|
164
|
+
* const memoizedProcess = memoizeFunction(
|
|
165
|
+
* (user: User) => processUser(user),
|
|
166
|
+
* (user) => user.name // Multiple users can have same name!
|
|
167
|
+
* );
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* @see https://en.wikipedia.org/wiki/Memoization
|
|
171
|
+
*/
|
|
172
|
+
const memoizeFunction = (fn, argsToCacheKey) => {
|
|
173
|
+
const mut_cache = new Map();
|
|
174
|
+
return (...args) => {
|
|
175
|
+
const key = argsToCacheKey(...args);
|
|
176
|
+
if (mut_cache.has(key)) {
|
|
177
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
178
|
+
return mut_cache.get(key);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
const result = fn(...args);
|
|
182
|
+
mut_cache.set(key, result);
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
export { memoizeFunction };
|
|
189
|
+
//# sourceMappingURL=memoize-function.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memoize-function.mjs","sources":["../../src/others/memoize-function.mts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0KG;MACU,eAAe,GAAG,CAK7B,EAAqB,EACrB,cAAiC,KACV;AACvB,IAAA,MAAM,SAAS,GAAG,IAAI,GAAG,EAAQ;AAEjC,IAAA,OAAO,CAAC,GAAG,IAAO,KAAO;AACvB,QAAA,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,IAAI,CAAC;AAEnC,QAAA,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;;AAEtB,YAAA,OAAO,SAAS,CAAC,GAAG,CAAC,GAAG,CAAE;;aACrB;AACL,YAAA,MAAM,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;AAE1B,YAAA,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC;AAE1B,YAAA,OAAO,MAAM;;AAEjB,KAAC;AACH;;;;"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a readonly tuple from the given arguments with precise literal type inference.
|
|
3
|
+
*
|
|
4
|
+
* This utility function provides a concise way to create tuples while preserving
|
|
5
|
+
* exact literal types. Without this function, TypeScript would infer arrays with
|
|
6
|
+
* widened types instead of tuples with literal types.
|
|
7
|
+
*
|
|
8
|
+
* **Key benefits:**
|
|
9
|
+
* - Preserves literal types (e.g., `1` instead of `number`)
|
|
10
|
+
* - Creates readonly tuples for immutability
|
|
11
|
+
* - Provides better type inference than array literals
|
|
12
|
+
* - Zero runtime overhead - just returns the arguments
|
|
13
|
+
*
|
|
14
|
+
* @template T - A tuple type with literal types inferred from the arguments
|
|
15
|
+
* @param args - The elements to include in the tuple (variadic)
|
|
16
|
+
* @returns A readonly tuple containing the provided arguments with preserved literal types
|
|
17
|
+
*
|
|
18
|
+
* @example Basic tuple creation with literal types
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // Without tp: types are widened
|
|
21
|
+
* const arr = [1, 'hello', true]; // (string | number | boolean)[]
|
|
22
|
+
*
|
|
23
|
+
* // With tp: exact literal types preserved
|
|
24
|
+
* const tuple = tp(1, 'hello', true); // readonly [1, 'hello', true]
|
|
25
|
+
* const coords = tp(10, 20); // readonly [10, 20]
|
|
26
|
+
* const single = tp('only'); // readonly ['only']
|
|
27
|
+
* const empty = tp(); // readonly []
|
|
28
|
+
*
|
|
29
|
+
* // TypeScript knows exact values at compile time
|
|
30
|
+
* type First = typeof tuple[0]; // 1 (literal type)
|
|
31
|
+
* type Second = typeof tuple[1]; // 'hello' (literal type)
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @example Creating type-safe coordinate systems
|
|
35
|
+
* ```typescript
|
|
36
|
+
* // 2D coordinates
|
|
37
|
+
* const point2D = tp(10, 20);
|
|
38
|
+
* const [x, y] = point2D; // x: 10, y: 20
|
|
39
|
+
*
|
|
40
|
+
* // 3D coordinates
|
|
41
|
+
* const point3D = tp(10, 20, 30);
|
|
42
|
+
* const [x3, y3, z3] = point3D; // Exact types preserved
|
|
43
|
+
*
|
|
44
|
+
* // Named coordinate system
|
|
45
|
+
* const namedPoint = tp('x', 100, 'y', 200);
|
|
46
|
+
* // Type: readonly ['x', 100, 'y', 200]
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @example Building type-safe data structures
|
|
50
|
+
* ```typescript
|
|
51
|
+
* // Creating a type-safe map structure
|
|
52
|
+
* const colorMap = [
|
|
53
|
+
* tp('red', '#FF0000'),
|
|
54
|
+
* tp('green', '#00FF00'),
|
|
55
|
+
* tp('blue', '#0000FF')
|
|
56
|
+
* ] as const;
|
|
57
|
+
* // Type: readonly [readonly ['red', '#FF0000'], ...]
|
|
58
|
+
*
|
|
59
|
+
* // Type-safe event system
|
|
60
|
+
* type EventTuple = readonly ['click', MouseEvent] | readonly ['change', Event];
|
|
61
|
+
* const event = tp('click', new MouseEvent('click')) as EventTuple;
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @example Function argument patterns
|
|
65
|
+
* ```typescript
|
|
66
|
+
* // Functions expecting exact tuple types
|
|
67
|
+
* function processCoordinate(coord: readonly [number, number]): void {
|
|
68
|
+
* const [x, y] = coord;
|
|
69
|
+
* console.log(`Processing point at (${x}, ${y})`);
|
|
70
|
+
* }
|
|
71
|
+
*
|
|
72
|
+
* processCoordinate(tp(10, 20)); // ✅ Type-safe
|
|
73
|
+
* processCoordinate([10, 20]); // ❌ Error: number[] not assignable
|
|
74
|
+
*
|
|
75
|
+
* // Pattern matching with tuples
|
|
76
|
+
* function handleMessage(msg: readonly ['error', string] | readonly ['success', any]) {
|
|
77
|
+
* if (msg[0] === 'error') {
|
|
78
|
+
* console.error(msg[1]); // TypeScript knows msg[1] is string
|
|
79
|
+
* } else {
|
|
80
|
+
* console.log('Success:', msg[1]);
|
|
81
|
+
* }
|
|
82
|
+
* }
|
|
83
|
+
*
|
|
84
|
+
* handleMessage(tp('error', 'Failed to load'));
|
|
85
|
+
* handleMessage(tp('success', { id: 123 }));
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* @example Advanced type inference
|
|
89
|
+
* ```typescript
|
|
90
|
+
* // Const assertions comparison
|
|
91
|
+
* const tuple1 = [1, 2, 3]; // number[]
|
|
92
|
+
* const tuple2 = [1, 2, 3] as const; // readonly [1, 2, 3]
|
|
93
|
+
* const tuple3 = tp(1, 2, 3); // readonly [1, 2, 3]
|
|
94
|
+
*
|
|
95
|
+
* // Building complex types
|
|
96
|
+
* const config = tp(
|
|
97
|
+
* tp('host', 'localhost'),
|
|
98
|
+
* tp('port', 3000),
|
|
99
|
+
* tp('secure', true)
|
|
100
|
+
* );
|
|
101
|
+
* // Type: readonly [
|
|
102
|
+
* // readonly ['host', 'localhost'],
|
|
103
|
+
* // readonly ['port', 3000],
|
|
104
|
+
* // readonly ['secure', true]
|
|
105
|
+
* // ]
|
|
106
|
+
*
|
|
107
|
+
* // Type-safe destructuring
|
|
108
|
+
* const [[, host], [, port], [, secure]] = config;
|
|
109
|
+
* // host: 'localhost', port: 3000, secure: true
|
|
110
|
+
* ```
|
|
111
|
+
*
|
|
112
|
+
* @example Integration with other utilities
|
|
113
|
+
* ```typescript
|
|
114
|
+
* import { pipe } from '../functional/pipe';
|
|
115
|
+
* import { Result } from '../functional/result';
|
|
116
|
+
*
|
|
117
|
+
* // Type-safe error handling
|
|
118
|
+
* function divide(a: number, b: number): Result<number, string> {
|
|
119
|
+
* if (b === 0) return Result.err('Division by zero');
|
|
120
|
+
* return Result.ok(a / b);
|
|
121
|
+
* }
|
|
122
|
+
*
|
|
123
|
+
* const calculation = tp(10, 2);
|
|
124
|
+
* const result = divide(...calculation); // Spread tuple as arguments
|
|
125
|
+
*
|
|
126
|
+
* // Building pipelines with tuples
|
|
127
|
+
* const pipeline = pipe(tp(5, 10))
|
|
128
|
+
* .map(([a, b]) => tp(a + b, a * b))
|
|
129
|
+
* .map(([sum, product]) => tp('sum', sum, 'product', product))
|
|
130
|
+
* .value;
|
|
131
|
+
* // Type: readonly ['sum', 15, 'product', 50]
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* @example Common patterns and use cases
|
|
135
|
+
* ```typescript
|
|
136
|
+
* // React-style state tuples
|
|
137
|
+
* const useState = <T>(initial: T) => tp(initial, (value: T) => void 0);
|
|
138
|
+
* const [count, setCount] = useState(0);
|
|
139
|
+
*
|
|
140
|
+
* // Redux-style actions
|
|
141
|
+
* const incrementAction = tp('INCREMENT', { amount: 1 });
|
|
142
|
+
* const decrementAction = tp('DECREMENT', { amount: 1 });
|
|
143
|
+
*
|
|
144
|
+
* // Database query results
|
|
145
|
+
* const queryResult = tp(
|
|
146
|
+
* true, // success
|
|
147
|
+
* [{ id: 1, name: 'John' }], // data
|
|
148
|
+
* null // error
|
|
149
|
+
* );
|
|
150
|
+
*
|
|
151
|
+
* // Configuration flags
|
|
152
|
+
* const features = tp('darkMode', 'analytics', 'notifications');
|
|
153
|
+
* const enabledFeatures = features.filter(f => isEnabled(f));
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* @see https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types
|
|
157
|
+
*/
|
|
158
|
+
export declare const tp: <const T extends readonly unknown[]>(...args: T) => Readonly<T>;
|
|
159
|
+
//# sourceMappingURL=tuple.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tuple.d.mts","sourceRoot":"","sources":["../../src/others/tuple.mts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4JG;AACH,eAAO,MAAM,EAAE,GAAI,KAAK,CAAC,CAAC,SAAS,SAAS,OAAO,EAAE,EACnD,GAAG,MAAM,CAAC,KACT,QAAQ,CAAC,CAAC,CAAS,CAAC"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a readonly tuple from the given arguments with precise literal type inference.
|
|
3
|
+
*
|
|
4
|
+
* This utility function provides a concise way to create tuples while preserving
|
|
5
|
+
* exact literal types. Without this function, TypeScript would infer arrays with
|
|
6
|
+
* widened types instead of tuples with literal types.
|
|
7
|
+
*
|
|
8
|
+
* **Key benefits:**
|
|
9
|
+
* - Preserves literal types (e.g., `1` instead of `number`)
|
|
10
|
+
* - Creates readonly tuples for immutability
|
|
11
|
+
* - Provides better type inference than array literals
|
|
12
|
+
* - Zero runtime overhead - just returns the arguments
|
|
13
|
+
*
|
|
14
|
+
* @template T - A tuple type with literal types inferred from the arguments
|
|
15
|
+
* @param args - The elements to include in the tuple (variadic)
|
|
16
|
+
* @returns A readonly tuple containing the provided arguments with preserved literal types
|
|
17
|
+
*
|
|
18
|
+
* @example Basic tuple creation with literal types
|
|
19
|
+
* ```typescript
|
|
20
|
+
* // Without tp: types are widened
|
|
21
|
+
* const arr = [1, 'hello', true]; // (string | number | boolean)[]
|
|
22
|
+
*
|
|
23
|
+
* // With tp: exact literal types preserved
|
|
24
|
+
* const tuple = tp(1, 'hello', true); // readonly [1, 'hello', true]
|
|
25
|
+
* const coords = tp(10, 20); // readonly [10, 20]
|
|
26
|
+
* const single = tp('only'); // readonly ['only']
|
|
27
|
+
* const empty = tp(); // readonly []
|
|
28
|
+
*
|
|
29
|
+
* // TypeScript knows exact values at compile time
|
|
30
|
+
* type First = typeof tuple[0]; // 1 (literal type)
|
|
31
|
+
* type Second = typeof tuple[1]; // 'hello' (literal type)
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @example Creating type-safe coordinate systems
|
|
35
|
+
* ```typescript
|
|
36
|
+
* // 2D coordinates
|
|
37
|
+
* const point2D = tp(10, 20);
|
|
38
|
+
* const [x, y] = point2D; // x: 10, y: 20
|
|
39
|
+
*
|
|
40
|
+
* // 3D coordinates
|
|
41
|
+
* const point3D = tp(10, 20, 30);
|
|
42
|
+
* const [x3, y3, z3] = point3D; // Exact types preserved
|
|
43
|
+
*
|
|
44
|
+
* // Named coordinate system
|
|
45
|
+
* const namedPoint = tp('x', 100, 'y', 200);
|
|
46
|
+
* // Type: readonly ['x', 100, 'y', 200]
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @example Building type-safe data structures
|
|
50
|
+
* ```typescript
|
|
51
|
+
* // Creating a type-safe map structure
|
|
52
|
+
* const colorMap = [
|
|
53
|
+
* tp('red', '#FF0000'),
|
|
54
|
+
* tp('green', '#00FF00'),
|
|
55
|
+
* tp('blue', '#0000FF')
|
|
56
|
+
* ] as const;
|
|
57
|
+
* // Type: readonly [readonly ['red', '#FF0000'], ...]
|
|
58
|
+
*
|
|
59
|
+
* // Type-safe event system
|
|
60
|
+
* type EventTuple = readonly ['click', MouseEvent] | readonly ['change', Event];
|
|
61
|
+
* const event = tp('click', new MouseEvent('click')) as EventTuple;
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @example Function argument patterns
|
|
65
|
+
* ```typescript
|
|
66
|
+
* // Functions expecting exact tuple types
|
|
67
|
+
* function processCoordinate(coord: readonly [number, number]): void {
|
|
68
|
+
* const [x, y] = coord;
|
|
69
|
+
* console.log(`Processing point at (${x}, ${y})`);
|
|
70
|
+
* }
|
|
71
|
+
*
|
|
72
|
+
* processCoordinate(tp(10, 20)); // ✅ Type-safe
|
|
73
|
+
* processCoordinate([10, 20]); // ❌ Error: number[] not assignable
|
|
74
|
+
*
|
|
75
|
+
* // Pattern matching with tuples
|
|
76
|
+
* function handleMessage(msg: readonly ['error', string] | readonly ['success', any]) {
|
|
77
|
+
* if (msg[0] === 'error') {
|
|
78
|
+
* console.error(msg[1]); // TypeScript knows msg[1] is string
|
|
79
|
+
* } else {
|
|
80
|
+
* console.log('Success:', msg[1]);
|
|
81
|
+
* }
|
|
82
|
+
* }
|
|
83
|
+
*
|
|
84
|
+
* handleMessage(tp('error', 'Failed to load'));
|
|
85
|
+
* handleMessage(tp('success', { id: 123 }));
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* @example Advanced type inference
|
|
89
|
+
* ```typescript
|
|
90
|
+
* // Const assertions comparison
|
|
91
|
+
* const tuple1 = [1, 2, 3]; // number[]
|
|
92
|
+
* const tuple2 = [1, 2, 3] as const; // readonly [1, 2, 3]
|
|
93
|
+
* const tuple3 = tp(1, 2, 3); // readonly [1, 2, 3]
|
|
94
|
+
*
|
|
95
|
+
* // Building complex types
|
|
96
|
+
* const config = tp(
|
|
97
|
+
* tp('host', 'localhost'),
|
|
98
|
+
* tp('port', 3000),
|
|
99
|
+
* tp('secure', true)
|
|
100
|
+
* );
|
|
101
|
+
* // Type: readonly [
|
|
102
|
+
* // readonly ['host', 'localhost'],
|
|
103
|
+
* // readonly ['port', 3000],
|
|
104
|
+
* // readonly ['secure', true]
|
|
105
|
+
* // ]
|
|
106
|
+
*
|
|
107
|
+
* // Type-safe destructuring
|
|
108
|
+
* const [[, host], [, port], [, secure]] = config;
|
|
109
|
+
* // host: 'localhost', port: 3000, secure: true
|
|
110
|
+
* ```
|
|
111
|
+
*
|
|
112
|
+
* @example Integration with other utilities
|
|
113
|
+
* ```typescript
|
|
114
|
+
* import { pipe } from '../functional/pipe';
|
|
115
|
+
* import { Result } from '../functional/result';
|
|
116
|
+
*
|
|
117
|
+
* // Type-safe error handling
|
|
118
|
+
* function divide(a: number, b: number): Result<number, string> {
|
|
119
|
+
* if (b === 0) return Result.err('Division by zero');
|
|
120
|
+
* return Result.ok(a / b);
|
|
121
|
+
* }
|
|
122
|
+
*
|
|
123
|
+
* const calculation = tp(10, 2);
|
|
124
|
+
* const result = divide(...calculation); // Spread tuple as arguments
|
|
125
|
+
*
|
|
126
|
+
* // Building pipelines with tuples
|
|
127
|
+
* const pipeline = pipe(tp(5, 10))
|
|
128
|
+
* .map(([a, b]) => tp(a + b, a * b))
|
|
129
|
+
* .map(([sum, product]) => tp('sum', sum, 'product', product))
|
|
130
|
+
* .value;
|
|
131
|
+
* // Type: readonly ['sum', 15, 'product', 50]
|
|
132
|
+
* ```
|
|
133
|
+
*
|
|
134
|
+
* @example Common patterns and use cases
|
|
135
|
+
* ```typescript
|
|
136
|
+
* // React-style state tuples
|
|
137
|
+
* const useState = <T>(initial: T) => tp(initial, (value: T) => void 0);
|
|
138
|
+
* const [count, setCount] = useState(0);
|
|
139
|
+
*
|
|
140
|
+
* // Redux-style actions
|
|
141
|
+
* const incrementAction = tp('INCREMENT', { amount: 1 });
|
|
142
|
+
* const decrementAction = tp('DECREMENT', { amount: 1 });
|
|
143
|
+
*
|
|
144
|
+
* // Database query results
|
|
145
|
+
* const queryResult = tp(
|
|
146
|
+
* true, // success
|
|
147
|
+
* [{ id: 1, name: 'John' }], // data
|
|
148
|
+
* null // error
|
|
149
|
+
* );
|
|
150
|
+
*
|
|
151
|
+
* // Configuration flags
|
|
152
|
+
* const features = tp('darkMode', 'analytics', 'notifications');
|
|
153
|
+
* const enabledFeatures = features.filter(f => isEnabled(f));
|
|
154
|
+
* ```
|
|
155
|
+
*
|
|
156
|
+
* @see https://www.typescriptlang.org/docs/handbook/2/objects.html#tuple-types
|
|
157
|
+
*/
|
|
158
|
+
const tp = (...args) => args;
|
|
159
|
+
|
|
160
|
+
export { tp };
|
|
161
|
+
//# sourceMappingURL=tuple.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tuple.mjs","sources":["../../src/others/tuple.mts"],"sourcesContent":[null],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4JG;AACI,MAAM,EAAE,GAAG,CAChB,GAAG,IAAO,KACM;;;;"}
|