Skip to content

ts-collections is a robust, Java-inspired collections framework for TypeScript, designed to provide developers with a powerful, type-safe, and feature-rich library for managing data structures. It is built with modern TypeScript features, ensuring high performance, scalability, and adherence to best practices.

License

Notifications You must be signed in to change notification settings

Karelaking/ts-collections

Repository files navigation

ts-collections

A robust, type-safe collections framework for TypeScript

License: MIT TypeScript npm version Vitest Visitors

FeaturesQuick StartAPI OverviewDocumentationContributing


🌟 Why ts-collections?

ts-collections is a Java-inspired collections framework that brings enterprise-grade data structures to TypeScript. Built with modern TypeScript features, it provides automatic type safety, familiar APIs for Java developers, and zero-configuration setup.

import { ArrayList, HashMap, HashSet } from 'ts-collections';

// Automatic type safety - no configuration needed!
const list = new ArrayList<number>();
list.add(42);           // ✅ Works
list.add("text" as any); // ❌ Runtime error (caught automatically)

// Familiar Java-style APIs
const map = new HashMap<string, User>();
map.put("john", user);
const value = map.get("john");

// Complete type inference
const set = new HashSet<string>();
set.add("unique");

✨ Features

🔒 Automatic Type Safety

Runtime type checking enabled by default - no configuration needed. Works just like Java's type-safe collections.

🎯 Zero Configuration

Type safety works out of the box. No need to learn validation libraries or configure schemas.

☕ Java-Friendly

Familiar Collections interface for Java developers. If you know Java Collections, you already know ts-collections.

🏗️ Extensible Architecture

Easy to create custom implementations through abstract base classes and clear interfaces.

📊 Performance Transparency

All operations documented with time/space complexity (O-notation).

✅ Battle-Tested

332/332 tests passing. Comprehensive test coverage for all implementations.

Coming from Java?

You'll feel right at home! Type safety works exactly like Java:

// Java
List<Integer> list = new ArrayList<>();
list.add(1);
list.add("text"); // ❌ Compile error

// TypeScript with ts-collections
const list = new ArrayList<number>();
list.add(1);
list.add("text" as any); // ❌ Runtime error (automatic!)

📖 Java Migration Guide →

📚 API Overview

Core Interfaces

Interface Description Key Methods
Collection<E> Base interface for all collections add(), remove(), size(), contains()
List<E> Ordered, indexed collection get(), set(), indexOf(), subList()
Set<E> Unique elements, no duplicates Inherits Collection with uniqueness
Map<K,V> Key-value associations put(), get(), containsKey(), entries()
Queue<E> FIFO processing offer(), poll(), peek()

Available Implementations

Type Implementation Characteristics
List ArrayList<E> Dynamic array, fast random access O(1)
List LinkedList<E> Doubly-linked, fast insertion/deletion
Set HashSet<E> Hash table, fast lookup O(1) average
Map HashMap<K,V> Hash table, fast key lookup O(1) average
Queue LinkedQueue<E> Linked list, FIFO operations O(1)

Architecture

graph TD
    A[Collection Interface] --> B[List]
    A --> C[Set]
    A --> D[Queue]
    E[Map Interface] --> F[HashMap]
    B --> G[ArrayList]
    B --> H[LinkedList]
    C --> I[HashSet]
    D --> J[LinkedQueue]
Loading

📦 Installation

npm install ts-collections
Other package managers
# Using pnpm
pnpm add ts-collections

# Using yarn
yarn add ts-collections

🚀 Quick Start

Lists - Ordered Collections

import { ArrayList } from 'ts-collections';

const list = new ArrayList<number>();
list.add(10);
list.add(20);
list.add(30);

console.log(list.get(0));     // 10
console.log(list.size());     // 3
list.removeAt(1);             // [10, 30]

Sets - Unique Elements

import { HashSet } from 'ts-collections';

const set = new HashSet<string>();
set.add("apple");
set.add("banana");
set.add("apple");  // Duplicate ignored

console.log(set.size());           // 2
console.log(set.contains("apple")); // true

Maps - Key-Value Pairs

import { HashMap } from 'ts-collections';

const map = new HashMap<string, number>();
map.put("Alice", 25);
map.put("Bob", 30);

console.log(map.get("Alice"));        // 25
console.log(map.containsKey("Bob"));  // true

Queues - FIFO Processing

import { LinkedQueue } from 'ts-collections';

const queue = new LinkedQueue<string>();
queue.offer("Task 1");
queue.offer("Task 2");

console.log(queue.poll());  // "Task 1"
console.log(queue.peek());  // "Task 2"

💡 Common Use Cases

Shopping Cart Example
import { ArrayList } from 'ts-collections';

interface Product {
  id: string;
  name: string;
  price: number;
}

class ShoppingCart {
  private items = new ArrayList<Product>();

  addItem(product: Product): void {
    this.items.add(product);
  }

  getTotalPrice(): number {
    return this.items.toArray().reduce((sum, item) => sum + item.price, 0);
  }
}

const cart = new ShoppingCart();
cart.addItem({ id: "1", name: "Laptop", price: 999 });
console.log(cart.getTotalPrice()); // 999
Session Management with Maps
import { HashMap } from 'ts-collections';

interface Session {
  userId: string;
  loginTime: Date;
}

class SessionManager {
  private sessions = new HashMap<string, Session>();

  createSession(userId: string): string {
    const sessionId = this.generateId();
    this.sessions.put(sessionId, { userId, loginTime: new Date() });
    return sessionId;
  }

  getSession(sessionId: string): Session | undefined {
    return this.sessions.get(sessionId);
  }
}
Task Queue Processing
import { LinkedQueue } from 'ts-collections';

const taskQueue = new LinkedQueue<string>();

// Add tasks
taskQueue.offer("Process payment");
taskQueue.offer("Send email");
taskQueue.offer("Update inventory");

// Process tasks
while (taskQueue.size() > 0) {
  const task = taskQueue.poll();
  console.log(`Processing: ${task}`);
}
Unique Tags with Sets
import { HashSet } from 'ts-collections';

class TagManager {
  private tags = new HashSet<string>();

  addTag(tag: string): boolean {
    return this.tags.add(tag.toLowerCase());
  }

  getTags(): string[] {
    return this.tags.toArray().sort();
  }
}

const tags = new TagManager();
tags.addTag("JavaScript");
tags.addTag("TypeScript");
tags.addTag("javascript"); // Duplicate ignored
console.log(tags.getTags()); // ["javascript", "typescript"]

Advanced: Custom Validation with Zod (Optional)

import { ArrayList } from 'ts-collections';
import { z } from 'zod';

// Advanced validation for power users
const strictNumbers = new ArrayList<number>({
    schema: z.number().positive().int()
});

strictNumbers.add(5);      // ✅ OK
strictNumbers.add(-1 as any);    // ❌ ERROR: must be positive
strictNumbers.add(3.14 as any);  // ❌ ERROR: must be integer

Note: Zod is optional - basic type safety works automatically without it!

🏗️ Design Principles

ts-collections follows SOLID principles for maintainable, extensible code:

  • Single Responsibility: Each class has one clear purpose
  • Open/Closed: Extend through abstract classes without modifying existing code
  • Liskov Substitution: Subclasses work anywhere their parent class works
  • Interface Segregation: Clean, focused interfaces
  • Dependency Inversion: Depend on abstractions, not concrete implementations

Building Custom Collections

Extend abstract base classes to create your own data structures:

import { AbstractList } from 'ts-collections';

class CustomList<E> extends AbstractList<E> {
  private elements: E[] = [];

  size(): number {
    return this.elements.length;
  }

  get(index: number): E {
    if (index < 0 || index >= this.size()) {
      throw new Error('Index out of bounds');
    }
    return this.elements[index];
  }

  // Implement remaining abstract methods...
}

📖 Documentation

Quick References

API Documentation

Generate full API docs with TypeDoc:

pnpm docs

🧪 Testing

All implementations have comprehensive test coverage (332/332 tests passing).

# Run all tests
pnpm test

# Watch mode
pnpm test --watch

# With coverage
pnpm test --coverage

🤝 Contributing

We welcome contributions! Here's how to get started:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Make your changes
  4. Test your changes: pnpm test
  5. Lint your code: pnpm lint
  6. Commit with clear messages
  7. Push to your branch
  8. Open a Pull Request

Development Setup

# Clone and install
git clone https://github.com/Karelaking/ts-collections.git
cd ts-collections
pnpm install

# Development workflow
pnpm test          # Run tests
pnpm lint          # Check code style
pnpm build         # Build the project
pnpm docs          # Generate documentation

For detailed guidelines, see CONTRIBUTING.md.

📊 Performance

All data structures document their performance characteristics:

Operation ArrayList HashSet HashMap LinkedQueue
Add/Put O(1)* O(1)* O(1)* O(1)
Get O(1) - O(1)* -
Remove O(n) O(1)* O(1)* O(1)
Contains O(n) O(1)* O(1)* O(n)
Size O(1) O(1) O(1) O(1)

* amortized time complexity

Run benchmarks: pnpm bench

📄 License

This project is licensed under the MIT License - see LICENSE for details.

🙏 Acknowledgments

🔗 Links


Made with ❤️ by the ts-collections team
⭐ Star us on GitHub if you find this useful!

About

ts-collections is a robust, Java-inspired collections framework for TypeScript, designed to provide developers with a powerful, type-safe, and feature-rich library for managing data structures. It is built with modern TypeScript features, ensuring high performance, scalability, and adherence to best practices.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Contributors 7