@naturalcycles/js-lib 15.42.1 → 15.44.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.
Files changed (43) hide show
  1. package/dist/array/array.util.d.ts +1 -21
  2. package/dist/array/array.util.js +0 -23
  3. package/dist/array/array2.d.ts +17 -0
  4. package/dist/array/array2.js +44 -0
  5. package/dist/array/index.d.ts +4 -0
  6. package/dist/array/index.js +4 -0
  7. package/dist/array/sort.d.ts +51 -0
  8. package/dist/array/sort.js +61 -0
  9. package/dist/array/sortedArray.d.ts +32 -0
  10. package/dist/array/sortedArray.js +55 -0
  11. package/dist/array/sortedSet.d.ts +22 -0
  12. package/dist/array/sortedSet.js +37 -0
  13. package/dist/datetime/localDate.d.ts +1 -2
  14. package/dist/datetime/localTime.d.ts +1 -2
  15. package/dist/log/commonLogger.d.ts +1 -1
  16. package/dist/math/math.util.js +3 -3
  17. package/dist/number/number.util.d.ts +0 -11
  18. package/dist/number/number.util.js +0 -13
  19. package/dist/object/keySortedMap.d.ts +9 -7
  20. package/dist/object/keySortedMap.js +1 -11
  21. package/dist/object/object.util.d.ts +1 -2
  22. package/dist/object/set2.d.ts +4 -0
  23. package/dist/object/set2.js +16 -0
  24. package/dist/semver.d.ts +1 -1
  25. package/dist/types.d.ts +23 -10
  26. package/dist/types.js +0 -7
  27. package/package.json +2 -2
  28. package/src/array/array.util.ts +1 -42
  29. package/src/array/array2.ts +52 -0
  30. package/src/array/index.ts +4 -0
  31. package/src/array/sort.ts +96 -0
  32. package/src/array/sortedArray.ts +78 -0
  33. package/src/array/sortedSet.ts +54 -0
  34. package/src/datetime/localDate.ts +2 -1
  35. package/src/datetime/localTime.ts +1 -1
  36. package/src/log/commonLogger.ts +1 -1
  37. package/src/math/math.util.ts +3 -3
  38. package/src/number/number.util.ts +0 -15
  39. package/src/object/keySortedMap.ts +10 -16
  40. package/src/object/object.util.ts +1 -1
  41. package/src/object/set2.ts +21 -1
  42. package/src/semver.ts +1 -1
  43. package/src/types.ts +25 -18
package/dist/types.d.ts CHANGED
@@ -273,9 +273,10 @@ export type SemVerString = string;
273
273
  */
274
274
  export type Reviver = (this: any, key: string, value: any) => any;
275
275
  /**
276
- * Like _stringMapValues, but values are sorted.
276
+ * Function to be passed to the `sort` method.
277
+ * Returns -1 | 0 | 1 canonically, but any positive/negative number is supported.
277
278
  */
278
- export declare function _stringMapValuesSorted<T>(map: StringMap<T>, mapper: Mapper<T, any>, dir?: SortDirection): T[];
279
+ export type Comparator<T> = (a: T, b: T) => number;
279
280
  /**
280
281
  * Needed due to https://github.com/microsoft/TypeScript/issues/13778
281
282
  * Only affects typings, no runtime effect.
@@ -328,6 +329,18 @@ export declare const _objectAssign: <T extends AnyObject>(target: T, part: Parti
328
329
  */
329
330
  export type ErrorDataTuple<T = unknown, ERR = Error> = [err: null, data: T] | [err: ERR, data: null];
330
331
  export type SortDirection = 'asc' | 'desc';
332
+ export interface MutateOptions {
333
+ /**
334
+ * Defaults to false.
335
+ */
336
+ mutate?: boolean;
337
+ }
338
+ export interface SortOptions extends MutateOptions {
339
+ /**
340
+ * Defaults to 'asc'.
341
+ */
342
+ dir?: SortDirection;
343
+ }
331
344
  export type Inclusiveness = '[]' | '[)';
332
345
  /**
333
346
  * @experimental
@@ -346,29 +359,29 @@ export type Promisable<T> = T | PromiseLike<T>;
346
359
  export type Class<T = any> = new (...args: any[]) => T;
347
360
  /**
348
361
  Convert `object`s, `Map`s, `Set`s, and `Array`s and all of their keys/elements into immutable structures recursively.
349
-
362
+
350
363
  This is useful when a deeply nested structure needs to be exposed as completely immutable, for example, an imported JSON module or when receiving an API response that is passed around.
351
-
364
+
352
365
  Please upvote [this issue](https://github.com/microsoft/TypeScript/issues/13923) if you want to have this type as a built-in in TypeScript.
353
-
366
+
354
367
  @example
355
368
  ```
356
369
  // data.json
357
370
  {
358
371
  "foo": ["bar"]
359
372
  }
360
-
373
+
361
374
  // main.ts
362
375
  import {ReadonlyDeep} from 'type-fest';
363
376
  import dataJson = require('./data.json');
364
-
377
+
365
378
  const data: ReadonlyDeep<typeof dataJson> = dataJson;
366
-
379
+
367
380
  export default data;
368
-
381
+
369
382
  // test.ts
370
383
  import data from './main';
371
-
384
+
372
385
  data.foo.push('bar');
373
386
  //=> error TS2339: Property 'push' does not exist on type 'readonly string[]'
374
387
  ```
package/dist/types.js CHANGED
@@ -1,4 +1,3 @@
1
- import { _sortBy } from './array/array.util.js';
2
1
  /**
3
2
  * Symbol to indicate END of Sequence.
4
3
  */
@@ -21,12 +20,6 @@ export const _noop = (..._args) => undefined;
21
20
  export const _passthroughPredicate = () => true;
22
21
  export const _passNothingPredicate = () => false;
23
22
  export const JWT_REGEX = /^[\w-]+\.[\w-]+\.[\w-]+$/;
24
- /**
25
- * Like _stringMapValues, but values are sorted.
26
- */
27
- export function _stringMapValuesSorted(map, mapper, dir = 'asc') {
28
- return _sortBy(_stringMapValues(map), mapper, { dir });
29
- }
30
23
  /**
31
24
  * Needed due to https://github.com/microsoft/TypeScript/issues/13778
32
25
  * Only affects typings, no runtime effect.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@naturalcycles/js-lib",
3
3
  "type": "module",
4
- "version": "15.42.1",
4
+ "version": "15.44.0",
5
5
  "dependencies": {
6
6
  "tslib": "^2",
7
7
  "undici": "^7",
@@ -13,7 +13,7 @@
13
13
  "@types/semver": "^7",
14
14
  "crypto-js": "^4",
15
15
  "dayjs": "^1",
16
- "@naturalcycles/dev-lib": "18.4.2"
16
+ "@naturalcycles/dev-lib": "20.7.0"
17
17
  },
18
18
  "exports": {
19
19
  ".": "./dist/index.js",
@@ -3,8 +3,8 @@ import type {
3
3
  AbortablePredicate,
4
4
  FalsyValue,
5
5
  Mapper,
6
+ MutateOptions,
6
7
  Predicate,
7
- SortDirection,
8
8
  StringMap,
9
9
  } from '../types.js'
10
10
  import { END } from '../types.js'
@@ -170,47 +170,6 @@ export function _groupBy<T>(items: readonly T[], mapper: Mapper<T, any>): String
170
170
  return map
171
171
  }
172
172
 
173
- export interface MutateOptions {
174
- /**
175
- * Defaults to false.
176
- */
177
- mutate?: boolean
178
- }
179
-
180
- export interface SortOptions extends MutateOptions {
181
- /**
182
- * Defaults to 'asc'.
183
- */
184
- dir?: SortDirection
185
- }
186
-
187
- /**
188
- * _sortBy([{age: 20}, {age: 10}], 'age')
189
- * // => [{age: 10}, {age: 20}]
190
- *
191
- * Same:
192
- * _sortBy([{age: 20}, {age: 10}], o => o.age)
193
- */
194
- export function _sortBy<T, COMPARE_TYPE extends string | number>(
195
- items: T[],
196
- mapper: Mapper<T, COMPARE_TYPE>,
197
- opt: SortOptions = {},
198
- ): T[] {
199
- const mod = opt.dir === 'desc' ? -1 : 1
200
-
201
- return (opt.mutate ? items : [...items]).sort((_a, _b) => {
202
- // This implementation may call mapper more than once per item,
203
- // but the benchmarks show no significant difference in performance.
204
- const a = mapper(_a)
205
- const b = mapper(_b)
206
- // if (typeof a === 'number' && typeof b === 'number') return (a - b) * mod
207
- // return String(a).localeCompare(String(b)) * mod
208
- if (a > b) return mod
209
- if (a < b) return -mod
210
- return 0
211
- })
212
- }
213
-
214
173
  /**
215
174
  * Similar to `Array.find`, but the `predicate` may return `END` to stop the iteration early.
216
175
  *
@@ -0,0 +1,52 @@
1
+ import { _shuffle } from './array.util.js'
2
+
3
+ /**
4
+ * Better Array.
5
+ *
6
+ * @experimental
7
+ */
8
+ export class Array2<T> extends Array<T> {
9
+ static override of<T>(...items: T[]): Array2<T> {
10
+ return new Array2(...items)
11
+ }
12
+
13
+ // eslint-disable-next-line @typescript-eslint/class-literal-property-style
14
+ get [Symbol.toStringTag](): string {
15
+ return 'Array2'
16
+ }
17
+
18
+ firstOrUndefined(): T | undefined {
19
+ return this[0]
20
+ }
21
+
22
+ first(): T {
23
+ if (!this.length) throw new Error('Array.first called on empty array')
24
+ return this[0]!
25
+ }
26
+
27
+ lastOrUndefined(): T | undefined {
28
+ return this[this.length - 1]
29
+ }
30
+
31
+ last(): T {
32
+ const { length } = this
33
+ if (!length) throw new Error('Array.last called on empty array')
34
+ return this[length - 1]!
35
+ }
36
+
37
+ uniq(): Array2<T> {
38
+ return new Array2<T>(...new Set(this))
39
+ }
40
+
41
+ shuffle(): Array2<T> {
42
+ return new Array2(..._shuffle(this))
43
+ }
44
+
45
+ isEmpty(): boolean {
46
+ return this.length === 0
47
+ }
48
+
49
+ isNotEmpty(): boolean {
50
+ return this.length !== 0
51
+ }
52
+ }
@@ -1,2 +1,6 @@
1
1
  export * from './array.util.js'
2
+ export * from './array2.js'
2
3
  export * from './range.js'
4
+ export * from './sort.js'
5
+ export * from './sortedArray.js'
6
+ export * from './sortedSet.js'
@@ -0,0 +1,96 @@
1
+ import {
2
+ _stringMapValues,
3
+ type Comparator,
4
+ type Mapper,
5
+ type SortDirection,
6
+ type SortOptions,
7
+ type StringMap,
8
+ } from '../types.js'
9
+
10
+ class Comparators {
11
+ /**
12
+ * Good for numbers.
13
+ */
14
+ numericAsc(a: number, b: number): number {
15
+ return a - b
16
+ }
17
+
18
+ numericDesc(a: number, b: number): number {
19
+ return b - a
20
+ }
21
+
22
+ localeAsc(a: string, b: string): number {
23
+ return a.localeCompare(b)
24
+ }
25
+
26
+ localeDesc(a: string, b: string): number {
27
+ return -a.localeCompare(b)
28
+ }
29
+
30
+ by<T, COMPARE_TYPE extends string | number>(
31
+ mapper: Mapper<T, COMPARE_TYPE>,
32
+ opt: ComparatorByOptions = {},
33
+ ): Comparator<T> {
34
+ const mod = opt.dir === 'desc' ? -1 : 1
35
+ return (objA: T, objB: T): number => {
36
+ // This implementation may call mapper more than once per item,
37
+ // but the benchmarks show no significant difference in performance.
38
+ const a = mapper(objA)
39
+ const b = mapper(objB)
40
+ if (a > b) return mod
41
+ if (a < b) return -mod
42
+ return 0
43
+ }
44
+ }
45
+
46
+ updatedAsc(a: { updated: number }, b: { updated: number }): number {
47
+ return a.updated - b.updated
48
+ }
49
+
50
+ updatedDesc(a: { updated: number }, b: { updated: number }): number {
51
+ return b.updated - a.updated
52
+ }
53
+
54
+ createdAsc(a: { created: number }, b: { created: number }): number {
55
+ return a.created - b.created
56
+ }
57
+
58
+ createdDesc(a: { created: number }, b: { created: number }): number {
59
+ return b.created - a.created
60
+ }
61
+ }
62
+
63
+ export const comparators = new Comparators()
64
+
65
+ interface ComparatorByOptions {
66
+ /**
67
+ * Defaults to 'asc'.
68
+ */
69
+ dir?: SortDirection
70
+ }
71
+
72
+ /**
73
+ * _sortBy([{age: 20}, {age: 10}], 'age')
74
+ * // => [{age: 10}, {age: 20}]
75
+ *
76
+ * Same:
77
+ * _sortBy([{age: 20}, {age: 10}], o => o.age)
78
+ */
79
+ export function _sortBy<T, COMPARE_TYPE extends string | number>(
80
+ items: T[],
81
+ mapper: Mapper<T, COMPARE_TYPE>,
82
+ opt: SortOptions = {},
83
+ ): T[] {
84
+ return (opt.mutate ? items : [...items]).sort(comparators.by(mapper, opt))
85
+ }
86
+
87
+ /**
88
+ * Like _stringMapValues, but values are sorted.
89
+ */
90
+ export function _stringMapValuesSorted<T>(
91
+ map: StringMap<T>,
92
+ mapper: Mapper<T, any>,
93
+ dir: SortDirection = 'asc',
94
+ ): T[] {
95
+ return _sortBy(_stringMapValues(map), mapper, { dir })
96
+ }
@@ -0,0 +1,78 @@
1
+ import type { Comparator } from '../types.js'
2
+ import { Array2 } from './array2.js'
3
+ import { comparators } from './sort.js'
4
+
5
+ export interface SortedArrayOptions<T> {
6
+ /**
7
+ * Defaults to undefined.
8
+ * Undefined (default comparator) works well for String keys.
9
+ * For Number keys - use comparators.numericAsc (or desc),
10
+ * otherwise sorting will be wrong (lexicographic).
11
+ */
12
+ comparator?: Comparator<T>
13
+ }
14
+
15
+ /**
16
+ * Like Array, but keeps values sorted after every insertion.
17
+ */
18
+ export class SortedArray<T> extends Array2<T> {
19
+ constructor(values: Iterable<T> = [], opt: SortedArrayOptions<T> = {}) {
20
+ super(...values)
21
+ this.#comparator = opt.comparator
22
+ this.resort()
23
+ }
24
+
25
+ readonly #comparator: Comparator<T> | undefined
26
+
27
+ override push(...values: T[]): number {
28
+ const length = super.push(...values)
29
+ this.resort()
30
+ return length
31
+ }
32
+
33
+ override unshift(...values: T[]): number {
34
+ const length = super.unshift(...values)
35
+ this.resort()
36
+ return length
37
+ }
38
+
39
+ override splice(start: number, deleteCount?: number, ...items: T[]): T[] {
40
+ const removed = super.splice(start, deleteCount ?? this.length - start, ...items)
41
+ if (items.length) {
42
+ this.resort()
43
+ }
44
+ return removed
45
+ }
46
+
47
+ static override get [Symbol.species](): ArrayConstructor {
48
+ return Array
49
+ }
50
+
51
+ override get [Symbol.toStringTag](): string {
52
+ return 'Array'
53
+ }
54
+
55
+ private resort(): void {
56
+ super.sort(this.#comparator)
57
+ }
58
+ }
59
+
60
+ export class SortedStringArray extends SortedArray<string> {
61
+ constructor(values: Iterable<string> = []) {
62
+ super(values)
63
+ }
64
+
65
+ override get [Symbol.toStringTag](): string {
66
+ return 'Array'
67
+ }
68
+ }
69
+
70
+ export class SortedNumberArray extends SortedArray<number> {
71
+ constructor(values: Iterable<number> = []) {
72
+ super(values, { comparator: comparators.numericAsc })
73
+ }
74
+
75
+ override get [Symbol.toStringTag](): string {
76
+ return 'Array'
77
+ }
78
+ }
@@ -0,0 +1,54 @@
1
+ import { Set2 } from '../object/index.js'
2
+ import type { Comparator } from '../types.js'
3
+
4
+ export interface SortedSetOptions<T> {
5
+ /**
6
+ * Defaults to undefined.
7
+ * Undefined (default comparator) works well for String keys.
8
+ * For Number keys - use comparators.numericAsc (or desc),
9
+ * otherwise sorting will be wrong (lexicographic).
10
+ */
11
+ comparator?: Comparator<T>
12
+ }
13
+
14
+ /**
15
+ * Like Set, but keeps members sorted after every insertion.
16
+ */
17
+ export class SortedSet<T> extends Set2<T> {
18
+ constructor(values: Iterable<T> = [], opt: SortedSetOptions<T> = {}) {
19
+ super()
20
+ this.#comparator = opt.comparator
21
+ this.addMany(values)
22
+ }
23
+
24
+ readonly #comparator: Comparator<T> | undefined
25
+
26
+ override add(value: T): this {
27
+ if (super.has(value)) {
28
+ return this
29
+ }
30
+ super.add(value)
31
+ return this.recreate()
32
+ }
33
+
34
+ override addMany(items: Iterable<T>): this {
35
+ for (const item of items) {
36
+ super.add(item)
37
+ }
38
+ return this.recreate()
39
+ }
40
+
41
+ private recreate(): this {
42
+ const items = Array.from(super.values())
43
+ items.sort(this.#comparator)
44
+ super.clear()
45
+ for (const item of items) {
46
+ super.add(item)
47
+ }
48
+ return this
49
+ }
50
+
51
+ override get [Symbol.toStringTag](): string {
52
+ return 'Set'
53
+ }
54
+ }
@@ -1,4 +1,3 @@
1
- import type { MutateOptions, SortOptions } from '../array/array.util.js'
2
1
  import { _assert } from '../error/assert.js'
3
2
  import { Iterable2 } from '../iter/iterable2.js'
4
3
  import type {
@@ -6,6 +5,8 @@ import type {
6
5
  IsoDate,
7
6
  IsoDateTime,
8
7
  MonthId,
8
+ MutateOptions,
9
+ SortOptions,
9
10
  UnixTimestamp,
10
11
  UnixTimestampMillis,
11
12
  } from '../types.js'
@@ -1,4 +1,3 @@
1
- import type { MutateOptions } from '../array/array.util.js'
2
1
  import { _assert } from '../error/assert.js'
3
2
  import type {
4
3
  IANATimezone,
@@ -6,6 +5,7 @@ import type {
6
5
  IsoDate,
7
6
  IsoDateTime,
8
7
  MonthId,
8
+ MutateOptions,
9
9
  NumberOfHours,
10
10
  NumberOfMinutes,
11
11
  SortDirection,
@@ -1,4 +1,4 @@
1
- import type { MutateOptions } from '../array/array.util.js'
1
+ import type { MutateOptions } from '../types.js'
2
2
 
3
3
  // copy-pasted to avoid weird circular dependency
4
4
  const _noop = (..._args: any[]): undefined => undefined
@@ -1,5 +1,5 @@
1
+ import { comparators } from '../array/sort.js'
1
2
  import { _assert } from '../error/assert.js'
2
- import { _sortNumbers } from '../number/number.util.js'
3
3
 
4
4
  /**
5
5
  * @returns Average of the array of numbers
@@ -49,7 +49,7 @@ export function _averageWeighted(values: number[], weights: number[]): number {
49
49
  * // 3
50
50
  */
51
51
  export function _percentile(values: number[], pc: number): number {
52
- const sorted = _sortNumbers(values)
52
+ const sorted = values.sort(comparators.numericAsc)
53
53
 
54
54
  // Floating pos in the range of [0; length - 1]
55
55
  const pos = ((values.length - 1) * pc) / 100
@@ -66,7 +66,7 @@ export function _percentile(values: number[], pc: number): number {
66
66
  export function _percentiles(values: number[], pcs: number[]): Record<number, number> {
67
67
  const r = {} as Record<number, number>
68
68
 
69
- const sorted = _sortNumbers(values)
69
+ const sorted = values.sort(comparators.numericAsc)
70
70
 
71
71
  for (const pc of pcs) {
72
72
  // Floating pos in the range of [0; length - 1]
@@ -1,4 +1,3 @@
1
- import type { SortOptions } from '../array/array.util.js'
2
1
  import type { Inclusiveness } from '../types.js'
3
2
 
4
3
  export function _randomInt(minIncl: number, maxIncl: number): number {
@@ -55,20 +54,6 @@ export function _clamp(x: number, minIncl: number, maxIncl: number): number {
55
54
  return x <= minIncl ? minIncl : x >= maxIncl ? maxIncl : x
56
55
  }
57
56
 
58
- /**
59
- * This function exists, because in JS you cannot just .sort() numbers,
60
- * as .sort() function first maps everything to String.
61
- *
62
- * @example
63
- *
64
- * _sortNumbers([1, 3, 2])
65
- * // [1, 2, 3]
66
- */
67
- export function _sortNumbers(numbers: number[], opt: SortOptions = {}): number[] {
68
- const mod = opt.dir === 'desc' ? -1 : 1
69
- return (opt.mutate ? numbers : [...numbers]).sort((a, b) => (a - b) * mod)
70
- }
71
-
72
57
  /**
73
58
  * Same as .toFixed(), but conveniently casts the output to Number.
74
59
  *
@@ -1,10 +1,13 @@
1
- export interface KeySortedMapOptions {
1
+ import type { Comparator } from '../types.js'
2
+
3
+ export interface KeySortedMapOptions<K> {
2
4
  /**
3
- * Defaults to false.
4
- * Set to true if your keys are numeric,
5
- * so it would sort correctly.
5
+ * Defaults to undefined.
6
+ * Undefined (default comparator) works well for String keys.
7
+ * For Number keys - use comparators.numericAsc (or desc),
8
+ * otherwise sorting will be wrong (lexicographic).
6
9
  */
7
- numericKeys?: boolean
10
+ comparator?: Comparator<K>
8
11
  }
9
12
 
10
13
  /**
@@ -24,7 +27,7 @@ export class KeySortedMap<K, V> implements Map<K, V> {
24
27
 
25
28
  constructor(
26
29
  entries: [K, V][] = [],
27
- public opt: KeySortedMapOptions = {},
30
+ public opt: KeySortedMapOptions<K> = {},
28
31
  ) {
29
32
  this.map = new Map(entries)
30
33
  this.sortedKeys = [...this.map.keys()]
@@ -220,15 +223,6 @@ export class KeySortedMap<K, V> implements Map<K, V> {
220
223
  }
221
224
 
222
225
  private sortKeys(): void {
223
- if (this.opt.numericKeys) {
224
- ;(this.sortedKeys as number[]).sort(numericAscCompare)
225
- } else {
226
- // Default sort - fastest for Strings
227
- this.sortedKeys.sort()
228
- }
226
+ this.sortedKeys.sort(this.opt.comparator)
229
227
  }
230
228
  }
231
-
232
- function numericAscCompare(a: number, b: number): number {
233
- return a - b
234
- }
@@ -1,8 +1,8 @@
1
- import type { MutateOptions } from '../array/array.util.js'
2
1
  import { _isEmpty, _isObject } from '../is.util.js'
3
2
  import type {
4
3
  AnyObject,
5
4
  KeyValueTuple,
5
+ MutateOptions,
6
6
  ObjectMapper,
7
7
  ObjectPredicate,
8
8
  Reviver,
@@ -6,6 +6,10 @@
6
6
  * @experimental
7
7
  */
8
8
  export class Set2<T = any> extends Set<T> {
9
+ static of<T>(items?: Iterable<T> | null): Set2<T> {
10
+ return new Set2(items)
11
+ }
12
+
9
13
  /**
10
14
  * Like .add(), but allows to add multiple items at once.
11
15
  * Mutates the Set, but also returns it conveniently.
@@ -17,6 +21,18 @@ export class Set2<T = any> extends Set<T> {
17
21
  return this
18
22
  }
19
23
 
24
+ first(): T {
25
+ if (!this.size) throw new Error('Set.first called on empty set')
26
+ return this.firstOrUndefined()!
27
+ }
28
+
29
+ firstOrUndefined(): T | undefined {
30
+ return this.values().next().value
31
+ }
32
+
33
+ // Last is not implemented, because it requires to traverse the whole Set - not optimal
34
+ // last(): T {
35
+
20
36
  toArray(): T[] {
21
37
  return [...this]
22
38
  }
@@ -25,5 +41,9 @@ export class Set2<T = any> extends Set<T> {
25
41
  return [...this]
26
42
  }
27
43
 
28
- // consider more helpful .toString() ?
44
+ override get [Symbol.toStringTag](): string {
45
+ return 'Set'
46
+ }
47
+
48
+ // todo: consider more helpful .toString() ?
29
49
  }
package/src/semver.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { SortOptions } from './array/array.util.js'
2
1
  import { _range } from './array/range.js'
3
2
  import { _assert } from './error/assert.js'
3
+ import type { SortOptions } from './types.js'
4
4
 
5
5
  export type SemverInput = string | Semver
6
6
  export type SemverInputNullable = SemverInput | null | undefined