-
Notifications
You must be signed in to change notification settings - Fork 37
Expand file tree
/
Copy pathset-methods.ts
More file actions
131 lines (121 loc) · 2.92 KB
/
set-methods.ts
File metadata and controls
131 lines (121 loc) · 2.92 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
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Set-like interface per TC39 spec: must have has, keys, and size
interface SetLike<T> {
has(value: T): boolean
keys(): IterableIterator<T>
readonly size: number
}
/*#__PURE__*/
export function union<T>(this: Set<T>, other: SetLike<T>): Set<T> {
const result = new Set<T>(this)
for (const value of other.keys()) {
result.add(value)
}
return result
}
/*#__PURE__*/
export function intersection<T>(this: Set<T>, other: SetLike<T>): Set<T> {
const result = new Set<T>()
for (const value of this) {
if (other.has(value)) {
result.add(value)
}
}
return result
}
/*#__PURE__*/
export function difference<T>(this: Set<T>, other: SetLike<T>): Set<T> {
const result = new Set<T>()
for (const value of this) {
if (!other.has(value)) {
result.add(value)
}
}
return result
}
/*#__PURE__*/
export function symmetricDifference<T>(this: Set<T>, other: SetLike<T>): Set<T> {
const result = new Set<T>(this)
for (const value of other.keys()) {
if (result.has(value)) {
result.delete(value)
} else {
result.add(value)
}
}
return result
}
/*#__PURE__*/
export function isSubsetOf<T>(this: Set<T>, other: SetLike<T>): boolean {
if (this.size > other.size) return false
for (const value of this) {
if (!other.has(value)) {
return false
}
}
return true
}
/*#__PURE__*/
export function isSupersetOf<T>(this: Set<T>, other: SetLike<T>): boolean {
for (const value of other.keys()) {
if (!this.has(value)) {
return false
}
}
return true
}
/*#__PURE__*/
export function isDisjointFrom<T>(this: Set<T>, other: SetLike<T>): boolean {
if (this.size <= other.size) {
for (const value of this) {
if (other.has(value)) {
return false
}
}
} else {
for (const value of other.keys()) {
if (this.has(value)) {
return false
}
}
}
return true
}
/*#__PURE__*/
export function isSupported(): boolean {
return (
'union' in Set.prototype &&
'intersection' in Set.prototype &&
'difference' in Set.prototype &&
'symmetricDifference' in Set.prototype &&
'isSubsetOf' in Set.prototype &&
'isSupersetOf' in Set.prototype &&
'isDisjointFrom' in Set.prototype
)
}
/*#__PURE__*/
export function isPolyfilled(): boolean {
const proto = Set.prototype as unknown as Record<string, unknown>
return (
'union' in Set.prototype &&
proto['union'] === union &&
proto['intersection'] === intersection &&
proto['difference'] === difference &&
proto['symmetricDifference'] === symmetricDifference &&
proto['isSubsetOf'] === isSubsetOf &&
proto['isSupersetOf'] === isSupersetOf &&
proto['isDisjointFrom'] === isDisjointFrom
)
}
export function apply(): void {
if (!isSupported()) {
Object.assign(Set.prototype, {
union,
intersection,
difference,
symmetricDifference,
isSubsetOf,
isSupersetOf,
isDisjointFrom,
})
}
}