@try.bivek/dsts
v2.0.0
Published
A lightweight, fully typed TypeScript library of essential data structures: LinkedList, Stack, Queue, and MinHeap.
Maintainers
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.tsdefinitions. - Dual ESM & CJS — works with both
importandrequire. - Tree-shakeable — import the whole library or a single structure via subpaths.
- Iterable — every structure supports
for...ofand 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 listMethods
| 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/pollin 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 iterableUse 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(); // 1Methods
| 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; prefertoArray()).
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(); // 9Methods
| 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-firstThe 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 featureUndo / 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
- NPM Package: @try.bivek/dsts
- Repository: github.com/gcbibek3353/dsts
Happy coding! 🚀
