Function argument validation for humans with expressive, chainable API
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Validation for JavaScript collection types including Map, Set, WeakMap, WeakSet, and Iterable objects with size constraints and content validation.
Validation for Set objects with size constraints and content checking methods.
/** Set validation predicate */
interface SetPredicate extends BasePredicate<Set<unknown>> {
// Size validation
size(size: number): SetPredicate;
minSize(size: number): SetPredicate;
maxSize(size: number): SetPredicate;
// Content validation
has<T>(...items: T[]): SetPredicate;
hasAny<T>(...items: T[]): SetPredicate;
deepEqual<T>(expected: Set<T>): SetPredicate;
ofType<T>(predicate: Predicate<T>): SetPredicate;
// State validation
readonly empty: SetPredicate;
readonly nonEmpty: SetPredicate;
}Usage Examples:
import ow from 'ow';
// Size validation
ow(new Set([1, 2, 3]), ow.set.size(3));
ow(new Set([1, 2]), ow.set.minSize(2));
ow(new Set([1, 2, 3]), ow.set.maxSize(5));
ow(new Set(), ow.set.empty);
ow(new Set([1]), ow.set.nonEmpty);
// Content validation
const numbers = new Set([1, 2, 3, 4, 5]);
ow(numbers, ow.set.has(1, 3, 5));
ow(numbers, ow.set.hasAny(2, 10, 20));
// Deep equality
ow(new Set([1, 2, 3]), ow.set.deepEqual(new Set([3, 2, 1])));
// Type validation - all values must match predicate
ow(new Set([1, 2, 3]), ow.set.ofType(ow.number.positive));
ow(new Set(['a', 'b', 'c']), ow.set.ofType(ow.string.alphabetical));
// Complex objects in sets
const userSet = new Set([
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
]);
ow(userSet, ow.set.ofType(ow.object.exactShape({
id: ow.number.integer.positive,
name: ow.string.nonEmpty
})));Validation for Map objects with size constraints and key/value validation methods.
/** Map validation predicate */
interface MapPredicate extends BasePredicate<Map<unknown, unknown>> {
// Size validation
size(size: number): MapPredicate;
minSize(size: number): MapPredicate;
maxSize(size: number): MapPredicate;
// Key validation
hasKeys<T1>(...keys: T1[]): MapPredicate;
hasAnyKeys<T1>(...keys: T1[]): MapPredicate;
keysOfType<T1>(predicate: Predicate<T1>): MapPredicate;
// Value validation
hasValues<T2>(...values: T2[]): MapPredicate;
hasAnyValues<T2>(...values: T2[]): MapPredicate;
valuesOfType<T2>(predicate: Predicate<T2>): MapPredicate;
// Equality validation
deepEqual<T1, T2>(expected: Map<T1, T2>): MapPredicate;
// State validation
readonly empty: MapPredicate;
readonly nonEmpty: MapPredicate;
}Usage Examples:
import ow from 'ow';
// Size validation
const userMap = new Map([
['alice', { age: 30 }],
['bob', { age: 25 }],
['charlie', { age: 35 }]
]);
ow(userMap, ow.map.size(3));
ow(userMap, ow.map.minSize(2));
ow(userMap, ow.map.maxSize(5));
ow(new Map(), ow.map.empty);
ow(userMap, ow.map.nonEmpty);
// Key and value validation
ow(userMap, ow.map.hasKeys('alice', 'bob'));
ow(userMap, ow.map.hasAnyKeys('alice', 'david'));
ow(userMap, ow.map.hasValues({ age: 30 }, { age: 25 }));
ow(userMap, ow.map.hasAnyValues({ age: 30 }, { age: 50 }));
// Type validation
ow(userMap, ow.map.keysOfType(ow.string.nonEmpty));
ow(userMap, ow.map.valuesOfType(ow.object.exactShape({
age: ow.number.integer.positive
})));
// Deep equality
const expectedMap = new Map([
['alice', { age: 30 }],
['bob', { age: 25 }]
]);
ow(expectedMap, ow.map.deepEqual(expectedMap));
// Number-keyed maps
const scoreMap = new Map([
[1, 'Alice'],
[2, 'Bob'],
[3, 'Charlie']
]);
ow(scoreMap, ow.map.keysOfType(ow.number.integer.positive));
ow(scoreMap, ow.map.valuesOfType(ow.string.nonEmpty));Validation for WeakSet objects with content checking methods.
/** WeakSet validation predicate */
interface WeakSetPredicate extends BasePredicate<WeakSet<object>> {
/** WeakSet must contain all specified items */
has<T>(...items: T[]): WeakSetPredicate;
/** WeakSet must contain any of the specified items */
hasAny<T>(...items: T[]): WeakSetPredicate;
}Usage Examples:
import ow from 'ow';
const obj1 = { id: 1 };
const obj2 = { id: 2 };
const obj3 = { id: 3 };
const weakSet = new WeakSet([obj1, obj2]);
// Basic WeakSet validation
ow(weakSet, ow.weakSet);
// Content validation
ow(weakSet, ow.weakSet.has(obj1, obj2));
ow(weakSet, ow.weakSet.hasAny(obj1, obj3));
// Note: WeakSet doesn't support size methods due to its weak natureValidation for WeakMap objects with key validation methods.
/** WeakMap validation predicate */
interface WeakMapPredicate extends BasePredicate<WeakMap<object, unknown>> {
/** WeakMap must contain all specified keys */
hasKeys<KeyType>(...keys: KeyType[]): WeakMapPredicate;
/** WeakMap must contain any of the specified keys */
hasAnyKeys<KeyType>(...keys: KeyType[]): WeakMapPredicate;
}Usage Examples:
import ow from 'ow';
const keyObj1 = { id: 'key1' };
const keyObj2 = { id: 'key2' };
const keyObj3 = { id: 'key3' };
const weakMap = new WeakMap([
[keyObj1, 'value1'],
[keyObj2, 'value2']
]);
// Basic WeakMap validation
ow(weakMap, ow.weakMap);
// Key validation
ow(weakMap, ow.weakMap.hasKeys(keyObj1, keyObj2));
ow(weakMap, ow.weakMap.hasAnyKeys(keyObj1, keyObj3));
// Note: WeakMap doesn't support value validation or size methods due to its weak natureValidation for objects that implement the Iterable interface.
/** Iterable validation predicate */
const iterable: Predicate<Iterable<unknown>>;Usage Examples:
import ow from 'ow';
// Basic iterables
ow([1, 2, 3], ow.iterable);
ow('hello', ow.iterable);
ow(new Set([1, 2, 3]), ow.iterable);
ow(new Map([['a', 1]]), ow.iterable);
// Custom iterables
const customIterable = {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
}
};
ow(customIterable, ow.iterable);
// Generator functions
function* numberGenerator() {
yield 1;
yield 2;
yield 3;
}
ow(numberGenerator(), ow.iterable);import ow from 'ow';
// Validate data transformation using collections
function processUniqueItems(items: unknown[]): Set<string> {
ow(items, ow.array.ofType(ow.string.nonEmpty));
const uniqueItems = new Set(items as string[]);
ow(uniqueItems, ow.set.nonEmpty);
ow(uniqueItems, ow.set.ofType(ow.string.nonEmpty));
return uniqueItems;
}
// Usage
const result = processUniqueItems(['apple', 'banana', 'apple', 'cherry']);
console.log(result); // Set(3) { 'apple', 'banana', 'cherry' }import ow from 'ow';
class Cache<K, V> {
private store = new Map<K, V>();
set(key: K, value: V): void {
ow(key, 'cacheKey', ow.any(ow.string, ow.number));
this.store.set(key, value);
// Validate store state
ow(this.store, ow.map.nonEmpty);
}
get(key: K): V | undefined {
ow(this.store, ow.map.hasKeys(key));
return this.store.get(key);
}
size(): number {
return this.store.size;
}
}
// Usage
const cache = new Cache<string, number>();
cache.set('count', 42);
ow(cache.size(), ow.number.equal(1));import ow from 'ow';
// Validate complex data structures
interface GraphNode {
id: string;
connections: Set<string>;
}
function validateGraph(nodes: Map<string, GraphNode>) {
// Validate map structure
ow(nodes, ow.map.nonEmpty);
ow(nodes, ow.map.keysOfType(ow.string.nonEmpty));
// Validate each node
ow(nodes, ow.map.valuesOfType(ow.object.exactShape({
id: ow.string.nonEmpty,
connections: ow.set.ofType(ow.string.nonEmpty)
})));
// Validate that all connections reference existing nodes
for (const [nodeId, node] of nodes) {
ow(nodeId, ow.string.equals(node.id));
for (const connectionId of node.connections) {
ow(nodes, ow.map.hasKeys(connectionId));
}
}
}import ow from 'ow';
// Using WeakMap for memory-efficient object metadata
const objectMetadata = new WeakMap();
function attachMetadata(obj: object, metadata: any) {
ow(obj, ow.object);
ow(metadata, ow.object.hasKeys('timestamp', 'type'));
objectMetadata.set(obj, metadata);
ow(objectMetadata, ow.weakMap.hasKeys(obj));
}
// Usage
const myObject = { data: 'example' };
attachMetadata(myObject, { timestamp: Date.now(), type: 'example' });Install with Tessl CLI
npx tessl i tessl/npm-ow