@geraintguan/ts-std-lib 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Geraint Guan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,147 @@
1
+ # @geraintguan/ts-std-lib
2
+
3
+ [![Coverage
4
+ Status](https://coveralls.io/repos/github/geraintguan/ts-std-lib/badge.svg?branch=main)](https://coveralls.io/github/geraintguan/ts-std-lib?branch=main)
5
+ [![Semantic Release: Conventional Commits](https://img.shields.io/badge/Semantic_Release-Conventional_Commits-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release)
6
+
7
+ [API Reference](https://ts-std-lib.geraint.io)
8
+
9
+ A practical and pragmatic standard library for TypeScript (and JavaScript).
10
+
11
+ ## Installation
12
+
13
+ ### NPM
14
+
15
+ ```shell
16
+ npm install -S @geraintguan/ts-std-lib
17
+ ```
18
+
19
+ ### PNPM
20
+
21
+ ```shell
22
+ pnpm add @geraintguan/ts-std-lib
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ### Data Structures
28
+
29
+ #### `HashMap`
30
+
31
+ [API Reference](https://ts-std-lib.geraint.io/classes/Data.HashMap.html)
32
+
33
+ Implementation of a key-value map that allows you to customise the way keys are
34
+ stored by using a custom hashing function.
35
+
36
+ ##### Example: `HashMap` of ISO8601 Date String keys
37
+
38
+ One useful example is using a HashMap that accepts `Date` objects as keys but
39
+ storing them as their [ISO8601 Date
40
+ Strings](https://en.wikipedia.org/wiki/ISO_8601).
41
+
42
+ ```typescript
43
+ import * as Std from "@geraintguan/ts-std-lib";
44
+
45
+ const map = Std.Data.HashMap.emptyWithCustomHash<Date, number, string>({
46
+ hash(date) {
47
+ data.toISOString();
48
+ },
49
+ });
50
+
51
+ const today = new Date("2024-11-01T12:00:00.000Z");
52
+ const tomorrow = new Date("2024-11-02T12:00:00.000Z");
53
+
54
+ map.set(today, 2);
55
+ map.set(tomorrow, 3);
56
+
57
+ [...map.keys()]; // => [
58
+ // "2024-11-01T12:00:00.000Z",
59
+ // "2024-11-02T12:00:00.000Z"
60
+ // ]
61
+ ```
62
+
63
+ #### `DefaultMap`
64
+
65
+ [API Reference](https://ts-std-lib.geraint.io/classes/Data.DefaultMap.html)
66
+
67
+ Implementation of a key-value map that allows you to customise the way keys are
68
+ stored by using a custom hashing function **and** specify either a value or
69
+ value generator function that will be returned when trying to access
70
+ non-existant keys.
71
+
72
+ ##### Example: `DefaultMap` of ID of documents with timestamp that defaults to current date and time
73
+
74
+ ```typescript
75
+ import * as Std from "@geraintguan/ts-std-lib";
76
+
77
+ type Document = {
78
+ id: string;
79
+ };
80
+
81
+ const map = Std.Data.DefaultMap.emptyWithCustomHash<Document, Date, string>({
82
+ defaultValue: {
83
+ type: "function",
84
+
85
+ value() {
86
+ return new Date(),
87
+ }
88
+ },
89
+ hash(document) {
90
+ return document.id;
91
+ },
92
+ });
93
+
94
+ const documentA = { id: "document-a" };
95
+ const documentB = { id: "document-b" };
96
+ const documentC = { id: "document-c" };
97
+
98
+ map.set(documentA, new Date("2020-01-01T00:00:00.000Z"));
99
+ map.set(documentB, new Date("2021-01-01T00:00:00.000Z"));
100
+
101
+ map.get(documentA).toISOString() // => "2020-01-01T00:00:00.000Z"
102
+ map.get(documentB).toISOString() // => "2021-01-01T00:00:00.000Z"
103
+ map.get(documentC).toISOString() // => new Date().toISOString()
104
+
105
+ [...map.keys()] // => [
106
+ // "document-a",
107
+ // "document-b",
108
+ // "document-c",
109
+ // ]
110
+ ```
111
+
112
+ ### Utility Functions
113
+
114
+ #### `constant()`
115
+
116
+ [API Reference](https://ts-std-lib.geraint.io/functions/constant.html)
117
+
118
+ Creates a function that always returns a specific value.
119
+
120
+ ##### Example
121
+
122
+ ```typescript
123
+ import * as Std from "@geraintguan/ts-std-lib";
124
+
125
+ const nine = Std.constant(9);
126
+
127
+ nine(); // => 9
128
+ nine(); // => 9
129
+ nine(); // => 9
130
+ ```
131
+
132
+ #### `identity()`
133
+
134
+ [API Reference](https://ts-std-lib.geraint.io/functions/identity.html)
135
+
136
+ Creates a function that always returns the value given to it as an argument.
137
+
138
+ ##### Example
139
+
140
+ ```typescript
141
+ import * as Std from "@geraintguan/ts-std-lib";
142
+
143
+ [true, false, true].filter(Std.identity); // => [
144
+ // true,
145
+ // true
146
+ // ]
147
+ ```
@@ -0,0 +1,310 @@
1
+ import { HashMap, HashMapOptions } from './HashMap.js';
2
+ /**
3
+ * Function called to filter the entries in a map.
4
+ *
5
+ * @remarks
6
+ *
7
+ * It is possible to mutate the original map as you filter the entries in the
8
+ * map though this is not recommended in most cases as it is easy to introduce
9
+ * bugs in your code this way.
10
+ *
11
+ * @param value - The value of the entry in the map being filtered.
12
+ * @param key - The key of the entry in the map being filtered.
13
+ * @param index - The index of the entry in the map being filtered.
14
+ * @param original - The original map instance being filtered.
15
+ *
16
+ * @returns `true` to include the entry in the new map or `false` to exclude it.
17
+ */
18
+ export type DefaultMapFilterFn<TKey, TValue, THashedKey, TDefaultValue extends TValue> = (value: TValue, key: THashedKey, index: number, original: DefaultMap<TKey, TValue, THashedKey, TDefaultValue>) => boolean;
19
+ export interface DefaultMapOptions<TKey, TValue, THashedKey = TKey, TDefaultValue extends TValue = TValue> extends HashMapOptions<TKey, THashedKey> {
20
+ defaultValue: DefaultMap<TKey, TValue, THashedKey, TDefaultValue>["defaultValue"];
21
+ }
22
+ /**
23
+ * Implementation of a specialised key-value map, based on map, that
24
+ * is created with a default value for retrieving keys that have not been set in
25
+ * the map.
26
+ *
27
+ * @remarks
28
+ *
29
+ * As this map is based of map it provides the same functionality
30
+ * such as the ability to customise the hashing function.
31
+ *
32
+ * When a default value is returned for a non-existent key, an entry is created
33
+ * for that key with the default value.
34
+ *
35
+ * @example Using a static value as the default value
36
+ * ```typescript
37
+ * const map = DefaultMap.empty<string, number>({
38
+ * defaultValue: { type: "value", value: 1 },
39
+ * });
40
+ *
41
+ * map.get("a"); // => 1
42
+ *
43
+ * map.set("b", 2);
44
+ * map.get("b"); // => 2
45
+ *
46
+ * [...map.keys()]; // => ["a", "b"]
47
+ * ```
48
+ *
49
+ * @example Using a function to generate the default value based on the key
50
+ * ```typescript
51
+ * const map = DefaultMap.empty<string, number>({
52
+ * defaultValue: { type: "function", value: (key) => key.length },
53
+ * });
54
+ *
55
+ * map.get("cat"); // => 3
56
+ * map.get("cat-dog"); // => 7
57
+ *
58
+ * map.set("dog", 4);
59
+ * map.get("dog"); // => 4
60
+ *
61
+ * [...map.keys()]; // => ["cat", "cat-dog", "dog"]
62
+ * ```
63
+ */
64
+ export declare class DefaultMap<TKey, TValue, THashedKey = TKey, TDefaultValue extends TValue = TValue> extends HashMap<TKey, TValue, THashedKey> {
65
+ /**
66
+ * Default value to use in this map when accessing keys that do not exist.
67
+ *
68
+ * @remarks
69
+ *
70
+ * Two types of default value are supported:
71
+ *
72
+ * 1. Providing a **function** will make the map call the given function that
73
+ * is called with the current access key to generate the default value.
74
+ *
75
+ * 2. Providing a static **value** that will be used as-is as the default
76
+ * value.
77
+ */
78
+ defaultValue: {
79
+ type: "function";
80
+ value: (key: TKey) => TDefaultValue;
81
+ } | {
82
+ type: "value";
83
+ value: TDefaultValue;
84
+ };
85
+ constructor(defaultValue: DefaultMap<TKey, TValue, THashedKey, TDefaultValue>["defaultValue"], hash: (key: TKey) => THashedKey, map?: Map<THashedKey, TValue>, name?: string);
86
+ /**
87
+ * Create a new empty map instance.
88
+ *
89
+ * @remarks
90
+ *
91
+ * This function uses the {@link identity} function as the hashing function
92
+ * meaning that keys will be stored without any changes.
93
+ *
94
+ * @see {@link DefaultMap.emptyWithCustomHash}
95
+ *
96
+ * @param options - Options to use to create the new map instance.
97
+ *
98
+ * @returns A new empty map instance.
99
+ */
100
+ static empty<TKey, TValue, TDefaultValue extends TValue = TValue>(options: Omit<DefaultMapOptions<TKey, TValue, TKey, TDefaultValue>, "hash">): DefaultMap<TKey, TValue, TKey, TDefaultValue>;
101
+ /**
102
+ * Create a new empty mao instance with a custom hashing function.
103
+ *
104
+ * @param options - Options to use to create the new map instance.
105
+ *
106
+ * @returns A new empty map instance.
107
+ */
108
+ static emptyWithCustomHash<TKey, TValue, THashedKey = TKey, TDefaultValue extends TValue = TValue>(options: DefaultMapOptions<TKey, TValue, THashedKey, TDefaultValue>): DefaultMap<TKey, TValue, THashedKey, TDefaultValue>;
109
+ /**
110
+ * Create a new map instance from an array of key-value pairs with a custom
111
+ * hashing function.
112
+ *
113
+ * @param entries - Array of key-value pairs to create the map
114
+ * with.
115
+ * @param options - Options to use to create the new map instance.
116
+ *
117
+ * @returns A new map instance with the given key-value pairs and a given
118
+ * custom hashing function.
119
+ */
120
+ static fromCustomEntries<TKey, TValue, THashedKey = TKey, TDefaultValue extends TValue = TValue>(entries: [TKey, TValue][], options: DefaultMapOptions<TKey, TValue, THashedKey, TDefaultValue>): DefaultMap<TKey, TValue, THashedKey, TDefaultValue>;
121
+ /**
122
+ * Create a new map instance from an array of key-value pairs
123
+ * using the {@link identity} as the hash function.
124
+ *
125
+ * @remarks
126
+ *
127
+ * This function uses the {@link identity} function as the hashing function
128
+ * meaning that keys will be stored without any changes.
129
+ *
130
+ * @example
131
+ * ```typescript
132
+ * const map = DefaultMap.fromEntries<number, string>([
133
+ * [1, "one"],
134
+ * [2, "two"],
135
+ * [3, "three"],
136
+ * ]);
137
+ *
138
+ * [...map];
139
+ * // => [
140
+ * // [1, "one"],
141
+ * // [2, "two"],
142
+ * // [3, "three"],
143
+ * // ];
144
+ * ```
145
+ *
146
+ * @param entries - Array of key-value pairs to create the map
147
+ * with.
148
+ * @param options - Options to use to create the new {map
149
+ * instance.
150
+ *
151
+ * @returns A new map instance with the given key-value pairs
152
+ * and default value.
153
+ */
154
+ static fromEntries<TKey, TValue, TDefaultValue extends TValue = TValue>(entries: [TKey, TValue][], options: Omit<DefaultMapOptions<TKey, TValue, TKey, TDefaultValue>, "hash">): DefaultMap<TKey, TValue, TKey, TDefaultValue>;
155
+ /**
156
+ * Returns a new map with only the key-value pairs where the given function
157
+ * returns `true`, filtering out those that the given function returns `false`
158
+ * for.
159
+ *
160
+ * @remarks
161
+ *
162
+ * The new map will have the same default value as this map.
163
+ *
164
+ * This function does not mutate the original map instance **unless** you call
165
+ * a mutating function on the map (4th argument) inside the given function.
166
+ *
167
+ * @example Include entries where key is greater than 2
168
+ * ```typescript
169
+ * const map = HashMap.fromEntries<number, string>([
170
+ * [1, "one"],
171
+ * [2, "two"],
172
+ * [3, "three"],
173
+ * [4, "four"],
174
+ * ], {
175
+ * defaultValue: {
176
+ * type: "value",
177
+ * value: "NaN",
178
+ * }
179
+ * });
180
+ *
181
+ * const filtered = map.filter((value, key) => key > 2);
182
+ *
183
+ * [...filtered];
184
+ * // => [
185
+ * // [3, "three"],
186
+ * // [4, "four"],
187
+ * // ]
188
+ * ```
189
+ * @example Include entries where the value has a length greater than 3
190
+ * ```typescript
191
+ * const map = DefaultMap.fromEntries<number, string>([
192
+ * [1, "one"],
193
+ * [2, "two"],
194
+ * [3, "three"],
195
+ * [4, "four"],
196
+ * ], {
197
+ * defaultValue: {
198
+ * type: "value",
199
+ * value: "NaN",
200
+ * }
201
+ * });
202
+ *
203
+ * const filtered = map.filter((value) => value.length > 3);
204
+ *
205
+ * [...filtered];
206
+ * // => [
207
+ * // [3, "three"],
208
+ * // [4, "four"],
209
+ * // ]
210
+ * ```
211
+ *
212
+ * @param fn - Function called for each key-value pair in the map that returns
213
+ * `true` to include the pair in the new map or `false` to exclude it.
214
+ *
215
+ * @returns A new map with only the key-value pairs where the given function
216
+ * returned `true` for.
217
+ */
218
+ filter(fn: DefaultMapFilterFn<TKey, TValue, THashedKey, TDefaultValue>): DefaultMap<TKey, TValue, THashedKey, TDefaultValue>;
219
+ /**
220
+ * Get the value with the given key from this map if it exists, if it doesn't
221
+ * return the default value configured for this map.
222
+ *
223
+ * @remarks
224
+ *
225
+ * Unlike {@link HashMap.get}, this method will not throw an error if the key
226
+ * does not exist in the map, instead returning the configured default value.
227
+ *
228
+ * Accessing an entry that does not exist with a key will set a new entry on
229
+ * the map with the given key and the created default value as the value of
230
+ * that entry.
231
+ *
232
+ * @param key - The key of the value to get.
233
+ *
234
+ * @returns The value with the given key in this map if it exists, if it
235
+ * doesn't then the default value configured for this map.
236
+ */
237
+ get(key: TKey): TDefaultValue | TValue;
238
+ /**
239
+ * Create a new map with entries that are the result of calling the given
240
+ * callback function on each of the key-value pairs in this map.
241
+ *
242
+ * @remarks
243
+ *
244
+ * The new map will have the same default value as this map.
245
+ *
246
+ * This function does not mutate the original map instance **unless** you call
247
+ * a mutating function on the map (4th argument) inside the given function.
248
+ *
249
+ * @example Swap the keys and values
250
+ * ```typescript
251
+ * const map = HashMap.fromEntries([
252
+ * ["one", 1],
253
+ * ["two", 2],
254
+ * ["three", 3],
255
+ * ], {
256
+ * defaultValue: {
257
+ * type: "value",
258
+ * value: "NaN",
259
+ * }
260
+ * });
261
+ *
262
+ * const swapped = map.map(([key, value]) => [value, key]);
263
+ * // => DefaultMap { 1 => "one", 2 => "two", 3 => "three" }
264
+ * ```
265
+ *
266
+ * @param fn - Function to call on each key-value pair in the map. The result
267
+ * of this function is used as entries in the new map.
268
+ *
269
+ * @returns A new map with the new entries from calling the given function on
270
+ * each key-value pair in the map.
271
+ */
272
+ map(fn: (value: TValue, key: THashedKey, index: number, original: DefaultMap<TKey, TValue, THashedKey, TDefaultValue>) => [THashedKey, TValue]): DefaultMap<TKey, TValue, THashedKey, TDefaultValue>;
273
+ /**
274
+ * Create a new map with entries that have keys that are the result of calling
275
+ * the given callback function on each of the key-value pairs in this map.
276
+ *
277
+ * @remarks
278
+ *
279
+ * The new map will have the same default value as this map.
280
+ *
281
+ * This function does not mutate the original map instance **unless** you call
282
+ * a mutating function on the map (4th argument) inside the given function.
283
+ *
284
+ * @param fn - Function to call on each key-value pair in the map. The result
285
+ * of this function is used as the keys for the entries in the new map.
286
+ *
287
+ * @returns A new map with the entries with new keys from calling the given
288
+ * function on each key-value pair in the map.
289
+ */
290
+ mapKeys(fn: (key: THashedKey, value: TValue, index: number, original: DefaultMap<TKey, TValue, THashedKey, TDefaultValue>) => THashedKey): DefaultMap<TKey, TValue, THashedKey, TDefaultValue>;
291
+ /**
292
+ * Create a new map with entries that have values that are the result of
293
+ * calling the given callback function on each of the key-value pairs in this
294
+ * map.
295
+ *
296
+ * @remarks
297
+ *
298
+ * The new map will have the same default value as this map.
299
+ *
300
+ * This function does not mutate the original map instance **unless** you call
301
+ * a mutating function on the map (4th argument) inside the given function.
302
+ *
303
+ * @param fn - Function to call on each key-value pair in the map. The result
304
+ * of this function is used as the values for the entries in the new map.
305
+ *
306
+ * @returns A new map with the entries with new values from calling the given
307
+ * function on each key-value pair in the map.
308
+ */
309
+ mapValues(fn: (value: TValue, key: THashedKey, index: number, original: DefaultMap<TKey, TValue, THashedKey, TDefaultValue>) => TValue): DefaultMap<TKey, TValue, THashedKey, TDefaultValue>;
310
+ }