CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ow

Function argument validation for humans with expressive, chainable API

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

collection-types.mddocs/

Collection Type Validation

Validation for JavaScript collection types including Map, Set, WeakMap, WeakSet, and Iterable objects with size constraints and content validation.

Capabilities

Set 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
})));

Map Validation

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));

WeakSet Validation

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 nature

WeakMap Validation

Validation 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 nature

Iterable Validation

Validation 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);

Advanced Usage Examples

Collection Transformation Validation

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' }

Caching Pattern Validation

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));

Data Structure Validation

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));
    }
  }
}

Memory-Efficient Collections

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

docs

advanced-features.md

builtin-types.md

collection-types.md

index.md

object-array-validation.md

primitive-types.md

typed-arrays.md

tile.json