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

fishdash

v0.3.1

Published

Functional utility library for modern TypeScript, ESM, ES6+!

Downloads

50

Readme

🐟 Fishdash

NPM version Tests TypeScript + ESM Install size Bundle size License Ask me in Telegram

🚀 Modern: Built with ESM6 modules and TypeScript
🪶 Lightweight: Tree-shakable functions for optimal bundle size
💪 Type-safe: Full TypeScript support with comprehensive type definitions
⚡ Fast: Optimized algorithms for maximum performance
🎯 Focused: Essential utility functions without bloat
📦 Zero Dependencies: No external dependencies

import { uniqBy } from 'fishdash';

const res = uniqBy([{val: 1}, {val: 2}, {val: 1}], item => item.val);

Features

Installation

Package Manager

Using npm:

npm install fishdash

Using yarn:

yarn add fishdash

Using pnpm:

pnpm add fishdash

Using bun:

bun add fishdash

Import

Import specific functions (recommended for tree-shaking):

import { map, groupBy, pick } from 'fishdash';

Import all functions:

import fishdash from 'fishdash';
// or
import * as fishdash from 'fishdash';

Quick Start

import { map, groupBy, pick, deepMerge } from 'fishdash';

// Working with arrays
const users = [
  { id: 1, name: 'Alice', age: 25, department: 'Engineering' },
  { id: 2, name: 'Bob', age: 30, department: 'Engineering' },
  { id: 3, name: 'Carol', age: 28, department: 'Marketing' }
];

// Extract names
const names = map(users, user => user.name);
// ['Alice', 'Bob', 'Carol']

// Group by department
const byDepartment = groupBy(users, user => user.department);
// {
//   Engineering: [{ id: 1, name: 'Alice', ... }, { id: 2, name: 'Bob', ... }],
//   Marketing: [{ id: 3, name: 'Carol', ... }]
// }

// Pick specific properties
const summary = pick(users[0], ['id', 'name']);
// { id: 1, name: 'Alice' }

// Deep merge objects
const config = deepMerge(
  { api: { timeout: 5000 } },
  { api: { retries: 3 }, debug: true }
);
// { api: { timeout: 5000, retries: 3 }, debug: true }

API Reference

Array Functions

map(object, mapper)

Transforms each value in an object using the mapper function and returns an array.

const users = { user1: { name: 'Alice' }, user2: { name: 'Bob' } };
const names = map(users, user => user.name);
// ['Alice', 'Bob']

groupBy(array, iteratee)

Groups array elements by the result of running each element through iteratee.

const inventory = [
  { name: 'apple', category: 'fruit' },
  { name: 'carrot', category: 'vegetable' },
  { name: 'banana', category: 'fruit' }
];

const grouped = groupBy(inventory, item => item.category);
// {
//   fruit: [{ name: 'apple', category: 'fruit' }, { name: 'banana', category: 'fruit' }],
//   vegetable: [{ name: 'carrot', category: 'vegetable' }]
// }

sortBy(array, iteratee)

Sorts array elements by the result of running each element through iteratee.

const users = [
  { name: 'Charlie', age: 30 },
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 35 }
];

const sortedByAge = sortBy(users, user => user.age);
// [{ name: 'Alice', age: 25 }, { name: 'Charlie', age: 30 }, { name: 'Bob', age: 35 }]

uniq(array) & uniqBy(array, iteratee)

Removes duplicate values from an array.

// Simple deduplication
const numbers = uniq([1, 2, 2, 3, 1, 4]);
// [1, 2, 3, 4]

// Deduplication by property
const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' },
  { id: 1, name: 'Alice' }
];
const uniqueUsers = uniqBy(users, user => user.id);
// [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }]

count(array, predicate) & countBy(array, iteratee)

Counts elements in an array.

// Count with predicate
const numbers = [1, 2, 3, 4, 5];
const evenCount = count(numbers, n => n % 2 === 0);
// 2

// Count by grouping
const fruits = ['apple', 'banana', 'apple', 'orange'];
const counts = countBy(fruits, fruit => fruit);
// { apple: 2, banana: 1, orange: 1 }

Object Functions

pick(object, keys) & pickBy(object, predicate)

Selects specific properties from an object.

const user = { id: 1, name: 'Alice', email: '[email protected]', password: 'secret' };

// Pick specific keys
const publicInfo = pick(user, ['id', 'name', 'email']);
// { id: 1, name: 'Alice', email: '[email protected]' }

// Pick by predicate
const nonSensitive = pickBy(user, (value, key) => key !== 'password');
// { id: 1, name: 'Alice', email: '[email protected]' }

omit(object, keys) & omitBy(object, predicate)

Excludes specific properties from an object.

const user = { id: 1, name: 'Alice', email: '[email protected]', password: 'secret' };

// Omit specific keys
const publicInfo = omit(user, ['password']);
// { id: 1, name: 'Alice', email: '[email protected]' }

// Omit by predicate
const withoutEmpty = omitBy({ a: 1, b: '', c: 3, d: null }, value => !value);
// { a: 1, c: 3 }

mapValues(object, iteratee)

Transforms values in an object while preserving keys.

const scores = { math: 85, science: 92, english: 78 };
const grades = mapValues(scores, score => score >= 90 ? 'A' : score >= 80 ? 'B' : 'C');
// { math: 'B', science: 'A', english: 'C' }

keyBy(array, iteratee)

Creates an object keyed by the result of running each array element through iteratee.

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];
const usersById = keyBy(users, user => user.id);
// { 1: { id: 1, name: 'Alice' }, 2: { id: 2, name: 'Bob' } }

deepMerge(...objects)

Recursively merges objects, concatenating arrays.

const obj1 = {
  api: { timeout: 5000 },
  features: ['auth']
};

const obj2 = {
  api: { retries: 3 },
  features: ['logging'],
  debug: true
};

const merged = deepMerge(obj1, obj2);
// {
//   api: { timeout: 5000, retries: 3 },
//   features: ['auth', 'logging'],
//   debug: true
// }

Utility Functions

fromPairs(pairs) & toPairs(object)

Converts between arrays of key-value pairs and objects.

// From pairs to object
const pairs = [['a', 1], ['b', 2], ['c', 3]];
const obj = fromPairs(pairs);
// { a: 1, b: 2, c: 3 }

// From object to pairs
const object = { x: 1, y: 2 };
const converted = toPairs(object);
// [['x', 1], ['y', 2]]

set(object, path, value) & setProps(object, props)

Sets values in objects.

// Set nested property
const user = {};
set(user, 'profile.name', 'Alice');
// { profile: { name: 'Alice' } }

// Set multiple properties
const updated = setProps(user, { age: 25, 'profile.email': '[email protected]' });
// { profile: { name: 'Alice', email: '[email protected]' }, age: 25 }

pad(string, length, chars)

Pads a string to a specified length.

const padded = pad('hello', 10, '-');
// '--hello---'

Conditional Functions

any(array, predicate) & every(array, predicate)

Tests array elements against a predicate.

const numbers = [1, 2, 3, 4, 5];

const hasEven = any(numbers, n => n % 2 === 0);
// true

const allPositive = every(numbers, n => n > 0);
// true

maxBy(array, iteratee) & minBy(array, iteratee)

Finds maximum/minimum values by a given criteria.

const users = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Carol', age: 22 }
];

const oldest = maxBy(users, user => user.age);
// { name: 'Bob', age: 30 }

const youngest = minBy(users, user => user.age);
// { name: 'Carol', age: 22 }

Type Definitions

Fishdash includes comprehensive TypeScript definitions:

// Generic mapper function type
type ObjectMapper<T> = (value: T, key?: string | number) => any;

// Object-like type for flexible input
type ObjectLike<T> = Record<string | number, T>;

// All functions are properly typed for intellisense and type safety
const users: User[] = [/* ... */];
const names: string[] = map(users, user => user.name); // Type-safe!

Tree Shaking

Fishdash is built with tree-shaking in mind. Import only what you need:

// ✅ Good - only imports the functions you use
import { map, filter } from 'fishdash';

// ❌ Avoid - imports the entire library
import fishdash from 'fishdash';
const result = fishdash.map(/* ... */);

Browser Support

Fishdash supports all modern browsers that support ES6+ features:

  • Chrome 61+
  • Firefox 60+
  • Safari 11+
  • Edge 79+

Performance

Fishdash is optimized for performance while maintaining readability:

  • Minimal runtime overhead
  • Efficient algorithms
  • No unnecessary object creation
  • Optimized for V8 engine

Inspired by

  • Lodash - A modern JavaScript utility library delivering modularity, performance & extras
  • Ramda - A practical functional library for JavaScript programmers
  • Underscore.js - JavaScript's utility belt

How to write TypeScript Libraries in 2025-2026

Contributing

We welcome contributions! Please follow these steps:

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes and add tests
  4. Ensure all tests pass (npm test)
  5. Commit your changes (git commit -m 'Add some amazing feature')
  6. Push to the branch (git push origin feature/amazing-feature)
  7. Open a Pull Request

Please read our Contributing Guide for detailed information.

Resources

License

MIT © Igor Suvorov


fishdash - Swimming in utilities 🐠