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

@try.bivek/dsts

v2.0.0

Published

A lightweight, fully typed TypeScript library of essential data structures: LinkedList, Stack, Queue, and MinHeap.

Readme

DSTS — Data Structures TypeScript

A lightweight, fully typed TypeScript library of essential data structures. Ships dual ESM + CommonJS builds, per-structure subpath imports for tree-shaking, and complete type definitions.

📦 Installation

npm i @try.bivek/dsts

✨ Features

  • Fully typed — generics throughout, complete .d.ts definitions.
  • Dual ESM & CJS — works with both import and require.
  • Tree-shakeable — import the whole library or a single structure via subpaths.
  • Iterable — every structure supports for...of and spread ([...ds]).
  • Zero runtime dependencies.

🚀 Quick Start

import {
  LinkedList,
  Stack,
  Queue,
  Deque,
  MinHeap,
  MaxHeap,
  PriorityQueue,
} from '@try.bivek/dsts';

const list = new LinkedList<number>();
list.insertAtHead(42);

const stack = new Stack<string>();
stack.push('Hello World');

const queue = new Queue<boolean>();
queue.offer(true);

const deque = new Deque<number>();
deque.addBack(1);
deque.addFront(0);

const minHeap = new MinHeap();
minHeap.insert(10);

const maxHeap = new MaxHeap();
maxHeap.insert(10);

const pq = new PriorityQueue<number>((a, b) => a - b);
pq.enqueue(5);

Subpath imports (tree-shaking)

Import just the structure you need — the rest is never bundled:

import LinkedList from '@try.bivek/dsts/linked-list';
import Stack from '@try.bivek/dsts/stack';
import Queue from '@try.bivek/dsts/queue';
import Deque from '@try.bivek/dsts/deque';
import MinHeap from '@try.bivek/dsts/min-heap';
import MaxHeap from '@try.bivek/dsts/max-heap';
import PriorityQueue from '@try.bivek/dsts/priority-queue';

CommonJS

const { LinkedList, PriorityQueue } = require('@try.bivek/dsts');

📚 Data Structures

LinkedList<T>

A generic singly linked list.

import { LinkedList } from '@try.bivek/dsts';

const list = LinkedList.from([1, 2, 3]); // 1 -> 2 -> 3

list.insertAtHead(0);     // 0 -> 1 -> 2 -> 3
list.insertAtTail(4);     // 0 -> 1 -> 2 -> 3 -> 4
list.insertAt(2, 9);      // 0 -> 1 -> 9 -> 2 -> 3 -> 4

list.contains(9);         // true
list.find(9)?.value;      // 9

list.deleteValue(9);      // removes first occurrence of 9
list.removeHead();        // 1  (removes & returns the head value)

list.reverse();           // reverses the list in place
list.toArray();           // T[] in head -> tail order
[...list];                // iterable

list.size();              // number of elements
list.isEmpty();           // boolean
list.clear();             // empties the list

Methods

| Method | Description | | --- | --- | | insertAtHead(value: T): void | Insert at the beginning. | | insertAtTail(value: T): void | Insert at the end. | | insertAt(index: number, value: T): void | Insert at an index (clamped to head/tail). | | removeHead(): T \| undefined | Remove and return the head value. | | deleteValue(value: T): void | Delete the first node matching value. | | find(value: T): ListNode<T> \| null | Return the first node matching value. | | contains(value: T): boolean | Whether a value exists in the list. | | reverse(): void | Reverse the list in place. | | toArray(): T[] | Snapshot as an array (head → tail). | | size(): number | Number of elements. | | isEmpty(): boolean | Whether the list is empty. | | clear(): void | Remove all elements. | | [Symbol.iterator]() | Iterate values head → tail. | | static from<T>(iterable): LinkedList<T> | Build a list from any iterable. |

Properties

  • head: ListNode<T> | null — reference to the first node.

Stack<T>

A generic LIFO (Last In, First Out) stack.

import { Stack } from '@try.bivek/dsts';

const stack = new Stack<string>();
stack.push('first');
stack.push('second');
stack.push('third');

stack.peek();      // 'third'
stack.pop();       // 'third'
stack.size();      // 2
stack.toArray();   // ['second', 'first']  (top -> bottom)
[...stack];        // iterable, top -> bottom
stack.isEmpty();   // false
stack.clear();

Methods

| Method | Description | | --- | --- | | push(value: T): void | Add an element to the top. | | pop(): T \| undefined | Remove and return the top element. | | peek(): T \| undefined | Return the top element without removing. | | size(): number | Number of elements. | | isEmpty(): boolean | Whether the stack is empty. | | clear(): void | Remove all elements. | | toArray(): T[] | Snapshot as an array (top → bottom). | | [Symbol.iterator]() | Iterate values top → bottom. |


Queue<T>

A generic FIFO (First In, First Out) queue. Backed by a linked list, so both ends are O(1).

import { Queue } from '@try.bivek/dsts';

const queue = new Queue<number>();
queue.offer(1);
queue.offer(2);
queue.offer(3);

queue.peek();      // 1
queue.poll();      // 1  (removes & returns the front)
queue.size();      // 2
queue.toArray();   // [2, 3]  (front -> back)
[...queue];        // iterable, front -> back
queue.isEmpty();   // false
queue.clear();

Note: enqueue/dequeue are named offer / poll in this library.

Methods

| Method | Description | | --- | --- | | offer(value: T): void | Add an element to the back (enqueue). | | poll(): T \| undefined | Remove and return the front element (dequeue). | | peek(): T \| undefined | Return the front element without removing. | | size(): number | Number of elements. | | isEmpty(): boolean | Whether the queue is empty. | | clear(): void | Remove all elements. | | toArray(): T[] | Snapshot as an array (front → back). | | [Symbol.iterator]() | Iterate values front → back. |


Deque<T>

A generic double-ended queue. Backed by a doubly linked list, so all four ends operations are O(1).

import { Deque } from '@try.bivek/dsts';

const dq = new Deque<number>();
dq.addBack(1);     // [1]
dq.addFront(0);    // [0, 1]
dq.addBack(2);     // [0, 1, 2]

dq.peekFront();    // 0
dq.peekBack();     // 2
dq.removeFront();  // 0
dq.removeBack();   // 2
dq.toArray();      // [1]  (front -> back)
[...dq];           // iterable, front -> back
dq.size();
dq.isEmpty();
dq.clear();

Deque.from([1, 2, 3]); // build from any iterable

Use it as a stack (addBack + removeBack) or a queue (addBack + removeFront).

Methods

| Method | Description | | --- | --- | | addFront(value: T): void | Add to the front. | | addBack(value: T): void | Add to the back. | | removeFront(): T \| undefined | Remove and return the front element. | | removeBack(): T \| undefined | Remove and return the back element. | | peekFront(): T \| undefined | Return the front element without removing. | | peekBack(): T \| undefined | Return the back element without removing. | | size(): number | Number of elements. | | isEmpty(): boolean | Whether the deque is empty. | | clear(): void | Remove all elements. | | toArray(): T[] | Snapshot as an array (front → back). | | [Symbol.iterator]() | Iterate values front → back. | | static from<T>(iterable): Deque<T> | Build a deque from any iterable. |


MinHeap

A binary min-heap for numbers (smallest element at the root).

import { MinHeap } from '@try.bivek/dsts';

const heap = new MinHeap();
heap.insert(10);
heap.insert(5);
heap.insert(15);
heap.insert(3);

heap.peek();      // 3   (minimum, without removing)
heap.getMin();    // 3   (removes & returns the minimum)
heap.getMin();    // 5
heap.size();      // 2
heap.toArray();   // copy in internal heap order (not sorted)
[...heap];        // iterable, internal heap order
heap.isEmpty();
heap.clear();

// O(n) build from an existing array
const h2 = MinHeap.heapify([5, 3, 8, 1, 9, 2]);
h2.getMin(); // 1

Methods

| Method | Description | | --- | --- | | insert(val: number): void | Insert a number. | | getMin(): number \| undefined | Remove and return the minimum. | | peek(): number \| undefined | Return the minimum without removing. | | size(): number | Number of elements. | | isEmpty(): boolean | Whether the heap is empty. | | clear(): void | Remove all elements. | | toArray(): number[] | Snapshot in internal heap order. | | [Symbol.iterator]() | Iterate values in internal heap order. | | static heapify(values: number[]): MinHeap | Build a heap from an array in O(n). |

Properties

  • heap: number[] — internal array representation (exposed for debugging; prefer toArray()).

To extract elements in sorted order, call getMin() repeatedly until the heap is empty.


MaxHeap

A binary max-heap for numbers (largest element at the root). Same API as MinHeap, with getMax instead of getMin.

import { MaxHeap } from '@try.bivek/dsts';

const heap = new MaxHeap();
heap.insert(10);
heap.insert(5);
heap.insert(15);

heap.peek();    // 15
heap.getMax();  // 15  (removes & returns the maximum)

const h2 = MaxHeap.heapify([5, 3, 8, 1, 9, 2]);
h2.getMax();    // 9

Methods

| Method | Description | | --- | --- | | insert(val: number): void | Insert a number. | | getMax(): number \| undefined | Remove and return the maximum. | | peek(): number \| undefined | Return the maximum without removing. | | size(): number | Number of elements. | | isEmpty(): boolean | Whether the heap is empty. | | clear(): void | Remove all elements. | | toArray(): number[] | Snapshot in internal heap order. | | [Symbol.iterator]() | Iterate values in internal heap order. | | static heapify(values: number[]): MaxHeap | Build a heap from an array in O(n). |

Properties

  • heap: number[] — internal array representation.

PriorityQueue<T>

A generic, comparator-based binary heap. Works with any type — numbers, strings, or objects.

By default it behaves as a min-priority-queue using natural ascending order (the "smallest" element is dequeued first). Pass a custom comparator to change the ordering.

import { PriorityQueue } from '@try.bivek/dsts';

// Default: min-first for numbers
const pq = new PriorityQueue<number>();
pq.enqueue(5);
pq.enqueue(1);
pq.enqueue(3);
pq.peek();      // 1
pq.dequeue();   // 1
pq.dequeue();   // 3

// Max-first via a custom comparator
const maxPq = new PriorityQueue<number>((a, b) => b - a);
[5, 1, 3].forEach((n) => maxPq.enqueue(n));
maxPq.dequeue(); // 5

// Objects ordered by a key
interface Task { name: string; priority: number; }
const tasks = new PriorityQueue<Task>((a, b) => a.priority - b.priority);
tasks.enqueue({ name: 'low',  priority: 5 });
tasks.enqueue({ name: 'high', priority: 1 });
tasks.dequeue(); // { name: 'high', priority: 1 }

// Build from an iterable (optional comparator)
PriorityQueue.from([5, 3, 8, 1]);                 // min-first
PriorityQueue.from([5, 3, 8, 1], (a, b) => b - a); // max-first

The comparator follows the standard Array.prototype.sort contract: return a negative number if a has higher priority than b (should come out first), positive if lower, 0 if equal.

Methods

| Method | Description | | --- | --- | | constructor(comparator?: (a: T, b: T) => number) | Create with an optional ordering (defaults to natural ascending). | | enqueue(value: T): void | Insert a value. | | dequeue(): T \| undefined | Remove and return the highest-priority value. | | peek(): T \| undefined | Return the highest-priority value without removing. | | size(): number | Number of elements. | | isEmpty(): boolean | Whether the queue is empty. | | clear(): void | Remove all elements. | | toArray(): T[] | Snapshot in internal heap order. | | [Symbol.iterator]() | Iterate values in internal heap order. | | static from<T>(iterable, comparator?): PriorityQueue<T> | Build from any iterable. |

Also exports the Comparator<T> type:

import { PriorityQueue, type Comparator } from '@try.bivek/dsts';

const byLength: Comparator<string> = (a, b) => a.length - b.length;
const pq = new PriorityQueue<string>(byLength);

🎯 Usage Examples

Task priority system

import { PriorityQueue } from '@try.bivek/dsts';

interface Task {
  id: string;
  priority: number;
  description: string;
}

// Lower priority number = handled first
const scheduler = new PriorityQueue<Task>((a, b) => a.priority - b.priority);

scheduler.enqueue({ id: '1', priority: 3, description: 'Ship feature' });
scheduler.enqueue({ id: '2', priority: 1, description: 'Fix outage' });
scheduler.enqueue({ id: '3', priority: 2, description: 'Review PR' });

while (!scheduler.isEmpty()) {
  const task = scheduler.dequeue()!;
  console.log(`Handling: ${task.description}`);
}
// Handling: Fix outage
// Handling: Review PR
// Handling: Ship feature

Undo / redo with stacks

import { Stack } from '@try.bivek/dsts';

interface Action { type: string; data: unknown }

class UndoRedoManager {
  private undoStack = new Stack<Action>();
  private redoStack = new Stack<Action>();

  execute(action: Action) {
    this.undoStack.push(action);
    this.redoStack.clear();
  }

  undo(): Action | undefined {
    const action = this.undoStack.pop();
    if (action) this.redoStack.push(action);
    return action;
  }

  redo(): Action | undefined {
    const action = this.redoStack.pop();
    if (action) this.undoStack.push(action);
    return action;
  }
}

Sliding-window maximum with a deque

import { Deque } from '@try.bivek/dsts';

function maxSlidingWindow(nums: number[], k: number): number[] {
  const result: number[] = [];
  const dq = new Deque<number>(); // holds indices, values decreasing

  for (let i = 0; i < nums.length; i++) {
    if (!dq.isEmpty() && dq.peekFront()! <= i - k) dq.removeFront();
    while (!dq.isEmpty() && nums[dq.peekBack()!]! < nums[i]!) dq.removeBack();
    dq.addBack(i);
    if (i >= k - 1) result.push(nums[dq.peekFront()!]!);
  }
  return result;
}

maxSlidingWindow([1, 3, -1, -3, 5, 3, 6, 7], 3); // [3, 3, 5, 5, 6, 7]

🔧 TypeScript Support

Every generic structure is fully typed:

const stringStack = new Stack<string>();

interface User { id: number; name: string }
const userQueue = new Queue<User>();

type Product = { id: string; price: number };
const productList = new LinkedList<Product>();

const highScores = new PriorityQueue<number>((a, b) => b - a);

📝 API Reference

ListNode<T>

Exposed by LinkedList (also importable: import { ListNode } from '@try.bivek/dsts/linked-list').

class ListNode<T> {
  value: T;
  next: ListNode<T> | null;
  constructor(value: T);
}

Comparator<T>

type Comparator<T> = (a: T, b: T) => number;

Time complexities

| Data Structure | Operation | Time | | --- | --- | --- | | LinkedList | insertAtHead / removeHead | O(1) | | LinkedList | insertAtTail / insertAt / deleteValue / find / contains / reverse | O(n) | | Stack | push / pop / peek | O(1) | | Queue | offer / poll / peek | O(1) | | Deque | addFront / addBack / removeFront / removeBack / peekFront / peekBack | O(1) | | MinHeap / MaxHeap | insert / getMin / getMax | O(log n) | | MinHeap / MaxHeap | peek | O(1) | | MinHeap / MaxHeap | heapify | O(n) | | PriorityQueue | enqueue / dequeue | O(log n) | | PriorityQueue | peek | O(1) |

size, isEmpty, and clear are O(1) for every structure. toArray and iteration are O(n).


🤝 Contributing

Contributions are welcome — please open an issue or pull request on GitHub.

Local development:

npm install
npm run typecheck   # tsc --noEmit
npm run build       # dual ESM + CJS build via tsup
npm test            # run the Vitest suite
npm run test:coverage

📄 License

MIT © Bivek Gharti

🔗 Links


Happy coding! 🚀