0
# Collection Type Validation
1
2
Validation for JavaScript collection types including Map, Set, WeakMap, WeakSet, and Iterable objects with size constraints and content validation.
3
4
## Capabilities
5
6
### Set Validation
7
8
Validation for Set objects with size constraints and content checking methods.
9
10
```typescript { .api }
11
/** Set validation predicate */
12
interface SetPredicate extends BasePredicate<Set<unknown>> {
13
// Size validation
14
size(size: number): SetPredicate;
15
minSize(size: number): SetPredicate;
16
maxSize(size: number): SetPredicate;
17
18
// Content validation
19
has<T>(...items: T[]): SetPredicate;
20
hasAny<T>(...items: T[]): SetPredicate;
21
deepEqual<T>(expected: Set<T>): SetPredicate;
22
ofType<T>(predicate: Predicate<T>): SetPredicate;
23
24
// State validation
25
readonly empty: SetPredicate;
26
readonly nonEmpty: SetPredicate;
27
}
28
```
29
30
**Usage Examples:**
31
32
```typescript
33
import ow from 'ow';
34
35
// Size validation
36
ow(new Set([1, 2, 3]), ow.set.size(3));
37
ow(new Set([1, 2]), ow.set.minSize(2));
38
ow(new Set([1, 2, 3]), ow.set.maxSize(5));
39
ow(new Set(), ow.set.empty);
40
ow(new Set([1]), ow.set.nonEmpty);
41
42
// Content validation
43
const numbers = new Set([1, 2, 3, 4, 5]);
44
ow(numbers, ow.set.has(1, 3, 5));
45
ow(numbers, ow.set.hasAny(2, 10, 20));
46
47
// Deep equality
48
ow(new Set([1, 2, 3]), ow.set.deepEqual(new Set([3, 2, 1])));
49
50
// Type validation - all values must match predicate
51
ow(new Set([1, 2, 3]), ow.set.ofType(ow.number.positive));
52
ow(new Set(['a', 'b', 'c']), ow.set.ofType(ow.string.alphabetical));
53
54
// Complex objects in sets
55
const userSet = new Set([
56
{ id: 1, name: 'Alice' },
57
{ id: 2, name: 'Bob' }
58
]);
59
60
ow(userSet, ow.set.ofType(ow.object.exactShape({
61
id: ow.number.integer.positive,
62
name: ow.string.nonEmpty
63
})));
64
```
65
66
### Map Validation
67
68
Validation for Map objects with size constraints and key/value validation methods.
69
70
```typescript { .api }
71
/** Map validation predicate */
72
interface MapPredicate extends BasePredicate<Map<unknown, unknown>> {
73
// Size validation
74
size(size: number): MapPredicate;
75
minSize(size: number): MapPredicate;
76
maxSize(size: number): MapPredicate;
77
78
// Key validation
79
hasKeys<T1>(...keys: T1[]): MapPredicate;
80
hasAnyKeys<T1>(...keys: T1[]): MapPredicate;
81
keysOfType<T1>(predicate: Predicate<T1>): MapPredicate;
82
83
// Value validation
84
hasValues<T2>(...values: T2[]): MapPredicate;
85
hasAnyValues<T2>(...values: T2[]): MapPredicate;
86
valuesOfType<T2>(predicate: Predicate<T2>): MapPredicate;
87
88
// Equality validation
89
deepEqual<T1, T2>(expected: Map<T1, T2>): MapPredicate;
90
91
// State validation
92
readonly empty: MapPredicate;
93
readonly nonEmpty: MapPredicate;
94
}
95
```
96
97
**Usage Examples:**
98
99
```typescript
100
import ow from 'ow';
101
102
// Size validation
103
const userMap = new Map([
104
['alice', { age: 30 }],
105
['bob', { age: 25 }],
106
['charlie', { age: 35 }]
107
]);
108
109
ow(userMap, ow.map.size(3));
110
ow(userMap, ow.map.minSize(2));
111
ow(userMap, ow.map.maxSize(5));
112
ow(new Map(), ow.map.empty);
113
ow(userMap, ow.map.nonEmpty);
114
115
// Key and value validation
116
ow(userMap, ow.map.hasKeys('alice', 'bob'));
117
ow(userMap, ow.map.hasAnyKeys('alice', 'david'));
118
ow(userMap, ow.map.hasValues({ age: 30 }, { age: 25 }));
119
ow(userMap, ow.map.hasAnyValues({ age: 30 }, { age: 50 }));
120
121
// Type validation
122
ow(userMap, ow.map.keysOfType(ow.string.nonEmpty));
123
ow(userMap, ow.map.valuesOfType(ow.object.exactShape({
124
age: ow.number.integer.positive
125
})));
126
127
// Deep equality
128
const expectedMap = new Map([
129
['alice', { age: 30 }],
130
['bob', { age: 25 }]
131
]);
132
133
ow(expectedMap, ow.map.deepEqual(expectedMap));
134
135
// Number-keyed maps
136
const scoreMap = new Map([
137
[1, 'Alice'],
138
[2, 'Bob'],
139
[3, 'Charlie']
140
]);
141
142
ow(scoreMap, ow.map.keysOfType(ow.number.integer.positive));
143
ow(scoreMap, ow.map.valuesOfType(ow.string.nonEmpty));
144
```
145
146
### WeakSet Validation
147
148
Validation for WeakSet objects with content checking methods.
149
150
```typescript { .api }
151
/** WeakSet validation predicate */
152
interface WeakSetPredicate extends BasePredicate<WeakSet<object>> {
153
/** WeakSet must contain all specified items */
154
has<T>(...items: T[]): WeakSetPredicate;
155
156
/** WeakSet must contain any of the specified items */
157
hasAny<T>(...items: T[]): WeakSetPredicate;
158
}
159
```
160
161
**Usage Examples:**
162
163
```typescript
164
import ow from 'ow';
165
166
const obj1 = { id: 1 };
167
const obj2 = { id: 2 };
168
const obj3 = { id: 3 };
169
170
const weakSet = new WeakSet([obj1, obj2]);
171
172
// Basic WeakSet validation
173
ow(weakSet, ow.weakSet);
174
175
// Content validation
176
ow(weakSet, ow.weakSet.has(obj1, obj2));
177
ow(weakSet, ow.weakSet.hasAny(obj1, obj3));
178
179
// Note: WeakSet doesn't support size methods due to its weak nature
180
```
181
182
### WeakMap Validation
183
184
Validation for WeakMap objects with key validation methods.
185
186
```typescript { .api }
187
/** WeakMap validation predicate */
188
interface WeakMapPredicate extends BasePredicate<WeakMap<object, unknown>> {
189
/** WeakMap must contain all specified keys */
190
hasKeys<KeyType>(...keys: KeyType[]): WeakMapPredicate;
191
192
/** WeakMap must contain any of the specified keys */
193
hasAnyKeys<KeyType>(...keys: KeyType[]): WeakMapPredicate;
194
}
195
```
196
197
**Usage Examples:**
198
199
```typescript
200
import ow from 'ow';
201
202
const keyObj1 = { id: 'key1' };
203
const keyObj2 = { id: 'key2' };
204
const keyObj3 = { id: 'key3' };
205
206
const weakMap = new WeakMap([
207
[keyObj1, 'value1'],
208
[keyObj2, 'value2']
209
]);
210
211
// Basic WeakMap validation
212
ow(weakMap, ow.weakMap);
213
214
// Key validation
215
ow(weakMap, ow.weakMap.hasKeys(keyObj1, keyObj2));
216
ow(weakMap, ow.weakMap.hasAnyKeys(keyObj1, keyObj3));
217
218
// Note: WeakMap doesn't support value validation or size methods due to its weak nature
219
```
220
221
### Iterable Validation
222
223
Validation for objects that implement the Iterable interface.
224
225
```typescript { .api }
226
/** Iterable validation predicate */
227
const iterable: Predicate<Iterable<unknown>>;
228
```
229
230
**Usage Examples:**
231
232
```typescript
233
import ow from 'ow';
234
235
// Basic iterables
236
ow([1, 2, 3], ow.iterable);
237
ow('hello', ow.iterable);
238
ow(new Set([1, 2, 3]), ow.iterable);
239
ow(new Map([['a', 1]]), ow.iterable);
240
241
// Custom iterables
242
const customIterable = {
243
*[Symbol.iterator]() {
244
yield 1;
245
yield 2;
246
yield 3;
247
}
248
};
249
250
ow(customIterable, ow.iterable);
251
252
// Generator functions
253
function* numberGenerator() {
254
yield 1;
255
yield 2;
256
yield 3;
257
}
258
259
ow(numberGenerator(), ow.iterable);
260
```
261
262
## Advanced Usage Examples
263
264
### Collection Transformation Validation
265
266
```typescript
267
import ow from 'ow';
268
269
// Validate data transformation using collections
270
function processUniqueItems(items: unknown[]): Set<string> {
271
ow(items, ow.array.ofType(ow.string.nonEmpty));
272
273
const uniqueItems = new Set(items as string[]);
274
275
ow(uniqueItems, ow.set.nonEmpty);
276
ow(uniqueItems, ow.set.ofType(ow.string.nonEmpty));
277
278
return uniqueItems;
279
}
280
281
// Usage
282
const result = processUniqueItems(['apple', 'banana', 'apple', 'cherry']);
283
console.log(result); // Set(3) { 'apple', 'banana', 'cherry' }
284
```
285
286
### Caching Pattern Validation
287
288
```typescript
289
import ow from 'ow';
290
291
class Cache<K, V> {
292
private store = new Map<K, V>();
293
294
set(key: K, value: V): void {
295
ow(key, 'cacheKey', ow.any(ow.string, ow.number));
296
this.store.set(key, value);
297
298
// Validate store state
299
ow(this.store, ow.map.nonEmpty);
300
}
301
302
get(key: K): V | undefined {
303
ow(this.store, ow.map.hasKeys(key));
304
return this.store.get(key);
305
}
306
307
size(): number {
308
return this.store.size;
309
}
310
}
311
312
// Usage
313
const cache = new Cache<string, number>();
314
cache.set('count', 42);
315
ow(cache.size(), ow.number.equal(1));
316
```
317
318
### Data Structure Validation
319
320
```typescript
321
import ow from 'ow';
322
323
// Validate complex data structures
324
interface GraphNode {
325
id: string;
326
connections: Set<string>;
327
}
328
329
function validateGraph(nodes: Map<string, GraphNode>) {
330
// Validate map structure
331
ow(nodes, ow.map.nonEmpty);
332
ow(nodes, ow.map.keysOfType(ow.string.nonEmpty));
333
334
// Validate each node
335
ow(nodes, ow.map.valuesOfType(ow.object.exactShape({
336
id: ow.string.nonEmpty,
337
connections: ow.set.ofType(ow.string.nonEmpty)
338
})));
339
340
// Validate that all connections reference existing nodes
341
for (const [nodeId, node] of nodes) {
342
ow(nodeId, ow.string.equals(node.id));
343
344
for (const connectionId of node.connections) {
345
ow(nodes, ow.map.hasKeys(connectionId));
346
}
347
}
348
}
349
```
350
351
### Memory-Efficient Collections
352
353
```typescript
354
import ow from 'ow';
355
356
// Using WeakMap for memory-efficient object metadata
357
const objectMetadata = new WeakMap();
358
359
function attachMetadata(obj: object, metadata: any) {
360
ow(obj, ow.object);
361
ow(metadata, ow.object.hasKeys('timestamp', 'type'));
362
363
objectMetadata.set(obj, metadata);
364
365
ow(objectMetadata, ow.weakMap.hasKeys(obj));
366
}
367
368
// Usage
369
const myObject = { data: 'example' };
370
attachMetadata(myObject, { timestamp: Date.now(), type: 'example' });
371
```