npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tstsx/collections

v0.0.2

Published

Custom data structures with hash function support for efficient object comparison.

Readme

@tstsx/collections

Custom data structures with hash function support for efficient object comparison.

Features

  • HashMap: Map implementation with custom hash functions for complex keys
  • HashSet: Set implementation with custom hash functions for complex values
  • Custom Hash Functions: Define your own equality logic for objects and complex types
  • Type-Safe: Full TypeScript support with generic types
  • Iterator Support: Works with for...of loops and spread operators

Installation

npm install @tstsx/collections

Usage

HashMap

Use HashMap when you need to use objects or complex types as keys with custom equality logic.

Basic Usage

import { HashMap } from '@tstsx/collections';

const map = new HashMap<string, number>();
map.set('foo', 1);
map.set('bar', 2);

console.log(map.get('foo')); // 1
console.log(map.has('bar')); // true
console.log(map.size); // 2

With Custom Hash Function

import { HashMap } from '@tstsx/collections';

type User = { id: number; name: string };

const userMap = new HashMap<User, string>({
  getHash: (user) => user.id,
});

const user1 = { id: 1, name: 'Alice' };
const user2 = { id: 2, name: 'Bob' };
const user3 = { id: 1, name: 'Alice Updated' };

userMap.set(user1, 'admin');
userMap.set(user2, 'user');
userMap.set(user3, 'super-admin'); // Overwrites user1 (same id)

console.log(userMap.get(user1)); // 'super-admin'
console.log(userMap.size); // 2

Iteration

const map = new HashMap<string, number>();
map.set('a', 1);
map.set('b', 2);

for (const [key, value] of map) {
  console.log(key, value);
}

Array.from(map.keys()); // ['a', 'b']
Array.from(map.values()); // [1, 2]
Array.from(map.entries()); // [['a', 1], ['b', 2]]

map.forEach((value, key) => {
  console.log(key, value);
});

HashSet

Use HashSet when you need to store unique values with custom equality logic.

Basic Usage

import { HashSet } from '@tstsx/collections';

const set = new HashSet<string>();
set.add('foo');
set.add('bar');
set.add('foo'); // Ignored (duplicate)

console.log(set.has('foo')); // true
console.log(set.size); // 2

With Custom Hash Function

import { HashSet } from '@tstsx/collections';

type Point = { x: number; y: number };

const points = new HashSet<Point>({
  getHash: (point) => `${point.x},${point.y}`,
});

const p1 = { x: 1, y: 2 };
const p2 = { x: 3, y: 4 };
const p3 = { x: 1, y: 2 }; // Same coordinates as p1

points.add(p1);
points.add(p2);
points.add(p3); // Ignored (same hash as p1)

console.log(points.size); // 2
console.log(points.has(p1)); // true
console.log(points.has(p3)); // true (same hash)

Iteration

const set = new HashSet<string>();
set.add('a');
set.add('b');

for (const value of set) {
  console.log(value);
}

Array.from(set); // ['a', 'b']
Array.from(set.values()); // ['a', 'b']

API

HashMap

Constructor

new HashMap<K, V>(options?: { getHash?: (key: K) => string | number | K })

Creates a new HashMap with an optional hash function. If no hash function is provided, keys are compared by reference.

Methods

  • get(key: K): V | undefined - Returns the value for the given key
  • set(key: K, value: V): this - Sets a key-value pair
  • has(key: K): boolean - Checks if a key exists
  • delete(key: K): boolean - Deletes a key-value pair
  • clear(): void - Removes all entries
  • keys(): IterableIterator<K> - Returns an iterator of keys
  • values(): IterableIterator<V> - Returns an iterator of values
  • entries(): IterableIterator<[K, V]> - Returns an iterator of key-value pairs
  • forEach(callback: (value: V, key: K, map: this) => void, thisArg?: any): void - Executes a function for each entry

Properties

  • size: number - The number of entries in the map

HashSet

Constructor

new HashSet<T>(options?: { getHash?: (value: T) => string | number | T })

Creates a new HashSet with an optional hash function. If no hash function is provided, values are compared by reference.

Methods

  • add(value: T): this - Adds a value to the set
  • has(value: T): boolean - Checks if a value exists
  • delete(value: T): boolean - Deletes a value
  • clear(): void - Removes all values
  • values(): IterableIterator<T> - Returns an iterator of values

Properties

  • size: number - The number of values in the set

Real-World Examples

Caching API Responses by Request Parameters

type Request = { url: string; method: string; body?: any };

const cache = new HashMap<Request, Response>({
  getHash: (req) => `${req.method}:${req.url}:${JSON.stringify(req.body)}`,
});

const req1 = { url: '/api/users', method: 'GET' };
const req2 = { url: '/api/users', method: 'POST', body: { name: 'Alice' } };

cache.set(req1, response1);
cache.set(req2, response2);

console.log(cache.get(req1)); // Returns cached response

Tracking Unique Visitors

type Visitor = { ip: string; userAgent: string };

const uniqueVisitors = new HashSet<Visitor>({
  getHash: (v) => `${v.ip}:${v.userAgent}`,
});

uniqueVisitors.add({ ip: '192.168.1.1', userAgent: 'Chrome' });
uniqueVisitors.add({ ip: '192.168.1.1', userAgent: 'Chrome' }); // Ignored
uniqueVisitors.add({ ip: '192.168.1.2', userAgent: 'Firefox' });

console.log(uniqueVisitors.size); // 2

Deduplicating Objects by ID

type Product = { id: string; name: string; price: number };

const products = new HashSet<Product>({
  getHash: (p) => p.id,
});

const rawData = [
  { id: '1', name: 'Laptop', price: 1000 },
  { id: '2', name: 'Mouse', price: 25 },
  { id: '1', name: 'Laptop Pro', price: 1200 }, // Duplicate ID
];

rawData.forEach((p) => products.add(p));
console.log(products.size); // 2 (duplicate removed)

Grouping Items with Complex Keys

type TimeRange = { start: Date; end: Date };

const schedules = new HashMap<TimeRange, string[]>({
  getHash: (range) => `${range.start.getTime()}-${range.end.getTime()}`,
});

const morning = { start: new Date('2025-01-01 09:00'), end: new Date('2025-01-01 12:00') };
const afternoon = { start: new Date('2025-01-01 13:00'), end: new Date('2025-01-01 17:00') };

schedules.set(morning, ['Meeting', 'Code Review']);
schedules.set(afternoon, ['Development', 'Testing']);

console.log(schedules.get(morning)); // ['Meeting', 'Code Review']

License

MIT