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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@danielgabbay/typescript-toolkit

v1.2.0

Published

Modern utility functions for TypeScript

Readme

TypeScript Toolkit

npm version npm downloads License: MIT TypeScript Build Status Coverage Bundle Size Tree Shakable

🚀 Modern utility functions for TypeScript development

A comprehensive, type-safe, and tree-shakable collection of utility functions designed specifically for TypeScript projects. Zero dependencies, full TypeScript support, and optimized for modern development workflows.

⚡ Quick Start

npm install @danielgabbay/typescript-toolkit
// Import everything
import * as toolkit from '@danielgabbay/typescript-toolkit';

// Tree-shakable imports (recommended)
import { chunk, unique, flatten } from '@danielgabbay/typescript-toolkit';
import { camelCase, slugify, truncate } from '@danielgabbay/typescript-toolkit';
import { deepClone, pick, merge } from '@danielgabbay/typescript-toolkit';
import { debounce, memoize, retry } from '@danielgabbay/typescript-toolkit';

// Usage examples
const users = [
  { name: 'john doe', age: 30, role: 'admin' },
  { name: 'jane smith', age: 25, role: 'user' },
  { name: 'bob johnson', age: 35, role: 'user' }
];

// Transform and process data
const chunks = chunk(users, 2);
const adminUsers = users.filter(u => u.role === 'admin');
const userNames = users.map(u => camelCase(u.name));
const settings = deepClone(config);

console.log(chunks); // [[{...}, {...}], [{...}]]
console.log(userNames); // ['johnDoe', 'janeSmith', 'bobJohnson']

🌟 Features

  • Tree-shakable - Import only what you need, reduce bundle size
  • TypeScript First - Full type safety and IntelliSense support
  • Zero Dependencies - Lightweight and secure
  • Modern ES Modules - Works with all modern bundlers
  • 97%+ Test Coverage - Thoroughly tested and reliable
  • Performance Optimized - Efficient implementations
  • Modular Design - Clean API with logical groupings

📚 API Documentation

Import

import { chunk, unique, groupBy, sum, mean } from 'typescript-toolkit/array';

Chunking & Splitting

chunk([1, 2, 3, 4, 5], 2);              // [[1, 2], [3, 4], [5]]
partition([1, 2, 3, 4], x => x % 2);     // [[2, 4], [1, 3]]

Uniqueness & Deduplication

unique([1, 2, 2, 3, 3, 3]);             // [1, 2, 3]
uniqueBy([{id: 1}, {id: 2}, {id: 1}], x => x.id); // [{id: 1}, {id: 2}]

Grouping & Indexing

const people = [
  { name: 'John', dept: 'IT' },
  { name: 'Jane', dept: 'HR' },
  { name: 'Bob', dept: 'IT' }
];
groupBy(people, p => p.dept);
// { IT: [{name: 'John', dept: 'IT'}, {name: 'Bob', dept: 'IT'}], HR: [...] }

Set Operations

union([1, 2], [2, 3], [3, 4]);          // [1, 2, 3, 4]
intersection([1, 2, 3], [2, 3, 4]);     // [2, 3]
difference([1, 2, 3], [2], [4]);        // [1, 3]

Statistics

sum([1, 2, 3, 4, 5]);                   // 15
mean([2, 4, 6]);                        // 4
median([1, 3, 5]);                      // 3

Search & Sort

binarySearch([1, 3, 5, 7, 9], 5);       // 2
sortBy(people, p => p.age, p => p.name); // Multi-key sorting

Import

import { compose, pipe, curry, debounce, memoize } from 'typescript-toolkit/function';

Function Composition

const add = (x: number) => x + 1;
const multiply = (x: number) => x * 2;

compose(add, multiply)(5);               // 11 (5 * 2 + 1)
pipe(add, multiply)(5);                  // 12 ((5 + 1) * 2)

Currying

const add = (a: number, b: number) => a + b;
const curriedAdd = curry(add);
curriedAdd(1)(2);                        // 3
curriedAdd(1, 2);                        // 3

Performance Control

const search = debounce(searchAPI, 300); // Debounce API calls
const expensiveFn = memoize(calculateResult); // Cache results

Error Handling

await retry(unstableAPI, 3, 1000);       // Retry 3 times with 1s delay
const result = tryCatch(() => riskyOperation(), 'default');

Import

import { deepClone, pick, omit, get, set } from 'typescript-toolkit/object';

Deep Operations

const original = { user: { profile: { name: 'John' } } };
const cloned = deepClone(original);      // Deep clone
deepMerge(target, source1, source2);     // Deep merge

Property Selection

const user = { id: 1, name: 'John', email: '[email protected]', password: 'secret' };
pick(user, 'id', 'name');               // { id: 1, name: 'John' }
omit(user, 'password');                  // { id: 1, name: 'John', email: '...' }

Path-based Access

const data = { user: { profile: { settings: { theme: 'dark' } } } };
get(data, 'user.profile.settings.theme', 'light'); // 'dark'
set(data, 'user.profile.settings.theme', 'light');

Transformation

mapKeys(obj, key => key.toUpperCase());   // Transform all keys
mapValues(obj, val => val * 2);          // Transform all values
invert({ a: '1', b: '2' });              // { '1': 'a', '2': 'b' }

Import

import { camelCase, kebabCase, slugify, isEmail } from 'typescript-toolkit/string';

Case Conversion

camelCase('hello world');                // 'helloWorld'
pascalCase('hello world');               // 'HelloWorld'
kebabCase('helloWorld');                 // 'hello-world'
snakeCase('helloWorld');                 // 'hello_world'

Formatting

capitalize('hello');                     // 'Hello'
titleCase('hello world');                // 'Hello World'
truncate('Long text here', 10);          // 'Long te...'
pad('hi', 6, '*');                       // '**hi**'

Validation

isEmail('[email protected]');             // true
isUrl('https://example.com');            // true
isNumeric('123.45');                     // true
isAlpha('Hello');                        // true

Advanced Manipulation

slugify('Hello World! 123');            // 'hello-world-123'
removeAccents('café naïve');             // 'cafe naive'
escapeHtml('<script>');                  // '&lt;script&gt;'

Import

import { isString, isNumber, assertType } from 'typescript-toolkit/type';

Type Guards

if (isString(value)) {
  // TypeScript knows value is string here
  console.log(value.toUpperCase());
}

isNumber(42);                           // true
isArray([1, 2, 3]);                     // true
isDefined(value);                       // true (not null/undefined)

Utility Types

type User = { name: string; age: number; settings: { theme: string } };
type PartialUser = DeepPartial<User>;    // All properties optional recursively
type ReadonlyUser = DeepReadonly<User>;  // All properties readonly recursively

Enum Utilities

const Colors = createEnum({ RED: 'red', BLUE: 'blue' });
getEnumValues(Colors);                   // ['red', 'blue']
isEnumValue(Colors, 'red');              // true

Type Assertions

const str = assertString(unknownValue); // Throws if not string
const num = assertNumber(userInput);    // Type-safe assertion

Import

import { time, benchmark, PerformanceTimer } from 'typescript-toolkit/performance';

Timing Functions

const { result, duration } = time(() => expensiveOperation());
const asyncResult = await timeAsync(async () => await fetchData());

Benchmarking

const stats = benchmark(() => sortArray(data), 1000);
console.log(`Average: ${stats.average}ms, Min: ${stats.min}ms`);

const asyncStats = await benchmarkAsync(async () => await apiCall(), 100);

Manual Timing

const timer = new PerformanceTimer();
timer.start();
// ... some operations
const elapsed = timer.duration; // Get current duration
timer.stop();
console.log(`Total time: ${timer.duration}ms`);

📈 Bundle Size Impact

TypeScript Toolkit is optimized for minimal bundle impact:

| Import Style | Bundle Size | Description | |--------------|-------------|-------------| | import { chunk } from 'typescript-toolkit/array' | ~0.3KB | Single function | | import { camelCase, slugify } from 'typescript-toolkit/string' | ~0.8KB | Multiple functions | | import * from 'typescript-toolkit' | ~25KB | Full library (not recommended) |

🚀 Advanced Usage Examples

Data Processing Pipeline

import { chunk, groupBy, sum } from 'typescript-toolkit/array';
import { pick, mapValues } from 'typescript-toolkit/object';
import { camelCase } from 'typescript-toolkit/string';

// Process user analytics data
const analytics = rawData
  .map(user => pick(user, 'id', 'name', 'purchases', 'signupDate'))
  .map(user => ({ ...user, name: camelCase(user.name) }))
  |> groupBy(%, user => user.signupDate.getMonth())
  |> mapValues(%, users => ({
      count: users.length,
      totalPurchases: sum(users.map(u => u.purchases))
    }));

API Response Transformation

import { deepClone, omit } from 'typescript-toolkit/object';
import { slugify, camelCase } from 'typescript-toolkit/string';

function transformApiResponse(response: ApiResponse) {
  const cleaned = omit(response, 'internal', 'debug');
  const normalized = deepClone(cleaned);
  
  // Transform all string fields to camelCase
  return mapValues(normalized, (value, key) => 
    typeof value === 'string' ? camelCase(value) : value
  );
}

Form Validation Helper

import { isEmail, isNumeric } from 'typescript-toolkit/string';
import { isDefined } from 'typescript-toolkit/type';

const validators = {
  required: (value: unknown) => isDefined(value) && value !== '',
  email: (value: string) => isEmail(value),
  numeric: (value: string) => isNumeric(value),
  minLength: (min: number) => (value: string) => value.length >= min
};

🛠️ Development

# Install dependencies
npm install

# Run tests in watch mode
npm run dev

# Run all tests
npm run test

# Check test coverage
npm run test:coverage

# Lint code
npm run lint

# Type check
npm run typecheck

# Build for production
npm run build

📊 Project Stats

  • 117 test cases with 97.77% coverage
  • 87 utility functions across 6 modules
  • Zero dependencies - completely self-contained
  • TypeScript 5.5+ - Latest features supported
  • ES2022 target - Modern JavaScript features
  • Automated releases - Semantic versioning with every push
  • Conventional commits - Structured commit messages for automatic changelog

🤝 Contributing

Contributions are welcome! This project uses conventional commits and semantic versioning.

Quick Contributing Guide:

  1. Fork and clone the repository
  2. Install dependencies: npm install
  3. Create feature branch: git checkout -b feat/your-feature
  4. Make changes and add tests
  5. Use conventional commits:
    git commit -m "feat(array): add new shuffle function"
    git commit -m "fix(string): handle edge case in camelCase"
    git commit -m "docs: update README examples"
  6. Push and create PR

Commit Types:

  • feat: → New feature (minor version bump)
  • fix: → Bug fix (patch version bump)
  • feat!: → Breaking change (major version bump)
  • docs: → Documentation changes
  • test: → Test updates
  • refactor: → Code refactoring

Automatic Releases:

Pushing to main with conventional commits triggers automatic:

  • Version bumping
  • NPM publishing
  • Changelog generation
  • GitHub releases

See PUBLISHING.md for detailed release process.

📄 License

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

⭐ Show your support

Give a ⭐️ if this project helped you!

☕ Support the Project

If TypeScript Toolkit has been helpful to you, consider supporting its development:

Buy Me A Coffee

Your support helps maintain and improve this project!

📞 Connect


⬆ back to top

Made with ❤️ by Daniel Gabbay