@contextjs/collections
A set of object-oriented collection types for TypeScript, designed for clarity, safety, and predictability in modern applications.
Features
- Fully type-safe generic collections
- Well-known data structures designed with a consistent and type-safe API (
List
,Dictionary
,Queue
,Stack
,HashSet
) - Consistent
null
handling for empty or missing values - Clean and minimal runtime behavior
- Optional value equality comparison in
HashSet<T>
- Zero external dependencies, tested and production-ready
Installation
bash
npm i @contextjs/collections
Quick Start
Jump to: API Reference • Design Notes • Testing
Examples:
This guide shows basic usage of all collection types in the @contextjs/collections
package.
Dictionary<TKey, TValue>
typescript
import { Dictionary } from '@contextjs/collections';
const dictionary = new Dictionary<string, number>();
dictionary.set("apple", 1);
dictionary.set("banana", 2);
console.log(dictionary.get("apple")); // 1
console.log(dictionary.has("banana")); // true
console.log(dictionary.has("cherry")); // false
dictionary.delete("banana");
console.log(dictionary.count()); // 1
dictionary.clear();
console.log(dictionary.count()); // 0
HashSet<T>
typescript
import { HashSet } from '@contextjs/collections';
type User = { id: number };
const users = new HashSet<User>((a, b) => a.id === b.id);
users.add({ id: 1 });
users.add({ id: 2 });
users.add({ id: 1 }); // Duplicate by id, ignored
console.log(users.count); // 2
console.log(users.has({ id: 1 })); // true (based on comparer)
console.log(users.has({ id: 3 })); // false
users.remove({ id: 1 });
console.log(users.count); // 1
typescript
// Also works with primitives using default equality
const ids = new HashSet<number>();
ids.add(1);
ids.add(1);
console.log(ids.count); // 1
List<T>
typescript
import { List } from '@contextjs/collections';
const list = new List<string>();
list.add("alpha");
list.add("beta");
list.add("gamma");
console.log(list.get(1)); // "beta"
console.log(list.count); // 3
list.remove(0); // removes "alpha"
console.log(list.get(0)); // "beta"
list.clear();
console.log(list.count); // 0
Queue<T>
typescript
import { Queue } from '@contextjs/collections';
const queue = new Queue<string>();
queue.enqueue("first");
queue.enqueue("second");
console.log(queue.peek); // "first"
console.log(queue.dequeue()); // "first"
console.log(queue.dequeue()); // "second"
console.log(queue.dequeue()); // null (empty)
queue.enqueue("third");
console.log(queue.count); // 1
queue.clear();
console.log(queue.isEmpty); // true
Stack<T>
typescript
import { Stack } from '@contextjs/collections';
const stack = new Stack<number>();
stack.push(10);
stack.push(20);
console.log(stack.current); // 20
console.log(stack.pop()); // 20
console.log(stack.pop()); // 10
console.log(stack.pop()); // null (empty)
stack.push(30);
console.log(stack.count); // 1
stack.clear();
console.log(stack.isEmpty); // true
API Reference
typescript
/**
* Represents a dictionary (key-value map) data structure.
* @template TKey The type of keys in the dictionary.
* @template TValue The type of values in the dictionary.
*/
export declare class Dictionary<TKey, TValue> {
/**
* Adds or replaces an item to the dictionary.
* @param key The key of the item.
* @param item The item to add.
*/
public set(key: TKey, item: TValue): void;
/**
* Gets an item from the dictionary.
* @param key The key of the item.
* @returns The item or null if not found.
*/
public get(key: TKey): TValue | null;
/**
* Checks if the dictionary contains a key.
* @param key The key to check.
* @returns True if the key exists, otherwise false.
*/
public has(key: TKey): boolean;
/**
* Removes an item from the dictionary.
* @param key The key of the item to remove.
*/
public delete(key: TKey): void;
/**
* Clears all items from the dictionary.
*/
public clear(): void;
/**
* Gets all values in the dictionary.
*/
public values(): TValue[];
/**
* Gets all keys in the dictionary.
*/
public keys(): TKey[];
/**
* Gets the number of items in the dictionary.
*/
public count(): number;
}
/**
* Represents a hash set (unique values) using custom equality comparison.
* @template T The type of elements in the set.
*/
export declare class HashSet<T> {
/**
* Creates a new hash set.
* @param equals Optional equality comparer. Defaults to strict equality (===).
*/
constructor(equals?: (a: T, b: T) => boolean);
/**
* Adds an item to the set if it doesn't already exist.
* @param item The item to add.
*/
public add(item: T): void;
/**
* Removes an item from the set.
* @param item The item to remove.
*/
public remove(item: T): void;
/**
* Checks whether the set contains an item.
* @param item The item to check.
* @returns True if the item exists, otherwise false.
*/
public has(item: T): boolean;
/**
* Clears all items from the set.
*/
public clear(): void;
/**
* Gets the number of items in the set.
*/
public get count(): number;
/**
* Indicates whether the set is empty.
*/
public get isEmpty(): boolean;
/**
* Converts the set to an array.
* @returns An array of set elements.
*/
public toArray(): T[];
}
/**
* Represents a list (dynamic array) data structure.
* @template T The type of elements in the list.
*/
export declare class List<T> {
/**
* Adds an item to the list.
* @param item The item to add.
*/
public add(item: T): void;
/**
* Removes an item from the list by index.
* @param index The index of the item to remove.
*/
public remove(index: number): void;
/**
* Gets an item from the list by index.
* @param index The index of the item to get.
* @returns The item or null if not found.
*/
public get(index: number): T | null;
/**
* Clears all items from the list.
*/
public clear(): void;
/**
* Gets the number of items in the list.
*/
public get count(): number;
/**
* Converts the list to an array.
* @returns An array of items in the list.
*/
public toArray(): T[];
}
/**
* Represents a queue (FIFO) data structure.
* @template T The type of elements in the queue.
*/
export declare class Queue<T> {
/**
* Enqueues an item into the queue.
* @param item The item to add.
*/
public enqueue(item: T): void;
/**
* Dequeues and returns the first item from the queue.
* @returns The dequeued item, or null if the queue is empty.
*/
public dequeue(): T | null;
/**
* Gets the item at the front of the queue without removing it.
*/
public get peek(): T | null;
/**
* Clears all items from the queue.
*/
public clear(): void;
/**
* Gets the number of items in the queue.
*/
public get count(): number;
/**
* Indicates whether the queue is empty.
*/
public get isEmpty(): boolean;
/**
* Converts the queue to an array.
* @returns An array of queue items in insertion order.
*/
public toArray(): T[];
}
/**
* Represents a stack (LIFO) data structure.
* @template T The type of elements in the stack.
*/
export declare class Stack<T> {
/**
* Pushes an element onto the stack.
* @param item The item to push.
*/
public push(item: T): void;
/**
* Pops an element off the stack.
* @returns The popped element, or null if the stack is empty.
*/
public pop(): T | null;
/**
* Gets the current element on the stack without removing it.
* @returns The current element, or null if the stack is empty.
*/
public get current(): T | null;
/**
* Clears all elements from the stack.
*/
public clear(): void;
/**
* Gets the number of elements in the stack.
*/
public get count(): number;
/**
* Indicates whether the stack is empty.
*/
public get isEmpty(): boolean;
/**
* Converts the stack to an array.
* @returns An array of stack elements in insertion order.
*/
public toArray(): T[];
}
/**
* Represents a binary search class for sorted arrays.
* @template T The type of elements in the array.
* This class provides a static method to perform binary search.
* It can use a custom comparison function or the default comparison.
* If a custom comparison function is not provided,
* it uses the default comparison based on the `<` and `>` operators.
*/
export declare class BinarySearch {
/**
* Performs a binary search on a sorted array.
* @template T The type of elements in the array.
* @param items The sorted array to search.
* @param target The item to search for.
* @param compare Optional comparison function. If not provided, uses default comparison.
* @returns The index of the target item, or -1 if not found.
*/
public static search<T>(items: T[], target: T, compare?: (a: T, b: T) => number): number;
/**
* Performs a binary search on a sorted array with a numeric target.
* @template T The type of elements in the array.
* @param items The sorted array to search.
* @param target The numeric value to search for.
* @param compare Comparison function that compares an item with a number.
* @returns The index of the target item, or -1 if not found.
*/
public static search<T>(items: T[], target: number, compare?: (a: T, b: number) => number): number;
}
Design Notes
These collections are written in TypeScript-first style with predictable, runtime-safe behavior:
null
is returned instead of throwing when an item is missing.HashSet<T>
supports structural equality with a custom comparer function.- Internals are designed to be lightweight, avoiding unnecessary abstraction.
Testing
This package maintains full test coverage for:
- All public collection methods
- Edge behavior on underflow, removal, or clear
- Equality comparison logic
- Type safety and mutation guarantees