-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
113 lines (88 loc) · 2.25 KB
/
index.ts
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
* @copyright Copyright (c) 2019-present Greg Hurrell
* @license MIT
*/
/**
* This is an ES6 Set stand-in for programming in an immutable style.
*
* In development will throw an error on attempted mutation (use of `add()`,
* `clear()` or `delete()`.
*
* NOTE: Implements "shallow" immutability only.
*/
export default class FrozenSet<T> implements Set<T> {
private isFrozen: boolean;
private storage: Set<T>;
constructor(
iterable?: Iterable<T> | null,
callback?: (s: FrozenSet<T>) => void,
) {
this.storage = new Set(iterable);
this.isFrozen = false;
if (callback != null) {
callback.call(this, this);
}
this.freeze();
}
clone(this: FrozenSet<T>, callback: (s: FrozenSet<T>) => void): FrozenSet<T> {
return new FrozenSet(this, callback);
}
freeze(this: FrozenSet<T>) {
this.isFrozen = true;
if (process.env.NODE_ENV !== 'production') {
Object.freeze(this.storage);
}
}
private assert(this: FrozenSet<T>) {
if (this.isFrozen) {
throw new Error('FrozenSet: Mutation Violation');
}
}
[Symbol.iterator](): IterableIterator<T> {
return this.storage[Symbol.iterator]();
}
add(value: T): this {
if (process.env.NODE_ENV !== 'production') {
this.assert();
}
this.storage.add(value);
return this;
}
clear(this: FrozenSet<T>): void {
if (process.env.NODE_ENV !== 'production') {
this.assert();
}
this.storage.clear();
}
delete(this: FrozenSet<T>, value: T): boolean {
if (process.env.NODE_ENV !== 'production') {
this.assert();
}
return this.storage.delete(value);
}
entries(): IterableIterator<[T, T]> {
return this.storage.entries();
}
forEach(
callbackfn: (value: T, value2: T, set: Set<T>) => void,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
thisArg?: any,
): void {
return this.storage.forEach(callbackfn, thisArg);
}
has(value: T): boolean {
return this.storage.has(value);
}
keys(): IterableIterator<T> {
return this.storage.keys();
}
values(): IterableIterator<T> {
return this.storage.values();
}
get [Symbol.toStringTag](): string {
return 'FrozenSet';
}
get size(): number {
return this.storage.size;
}
}