forked from rocicorp/mono
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcustom-key-set.ts
More file actions
73 lines (60 loc) · 1.68 KB
/
custom-key-set.ts
File metadata and controls
73 lines (60 loc) · 1.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
type Primitive = undefined | null | boolean | string | number | symbol | bigint;
/**
* A {@link Set} that uses a custom value transformation function to convert values
* to a primitive type that can be used as a {@link Set} value.
*
* This allows for using objects as values in a {@link Set} without worrying about
* reference equality.
*/
export class CustomKeySet<V> {
readonly [Symbol.toStringTag] = 'CustomKeySet';
readonly #toKey: (value: V) => Primitive;
readonly #map = new Map<Primitive, V>();
constructor(toKey: (value: V) => Primitive, iterable?: Iterable<V> | null) {
this.#toKey = toKey;
if (iterable) {
for (const value of iterable ?? []) {
this.#map.set(toKey(value), value);
}
}
}
add(value: V): this {
this.#map.set(this.#toKey(value), value);
return this;
}
clear(): void {
this.#map.clear();
}
delete(value: V): boolean {
return this.#map.delete(this.#toKey(value));
}
forEach(
callbackfn: (value: V, value2: V, set: CustomKeySet<V>) => void,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
thisArg?: any,
): void {
this.#map.forEach(value => {
callbackfn.call(thisArg, value, value, this);
});
}
has(value: V): boolean {
return this.#map.has(this.#toKey(value));
}
get size(): number {
return this.#map.size;
}
*entries(): IterableIterator<[V, V]> {
for (const value of this.#map.values()) {
yield [value, value];
}
}
keys(): IterableIterator<V> {
return this.#map.values();
}
values(): IterableIterator<V> {
return this.#map.values();
}
[Symbol.iterator](): IterableIterator<V> {
return this.#map.values();
}
}