fishdash
v0.3.1
Published
Functional utility library for modern TypeScript, ESM, ES6+!
Downloads
50
Maintainers
Readme
🐟 Fishdash
🚀 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 fishdashUsing yarn:
yarn add fishdashUsing pnpm:
pnpm add fishdashUsing bun:
bun add fishdashImport
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);
// truemaxBy(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:
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Make your changes and add tests
- Ensure all tests pass (
npm test) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Please read our Contributing Guide for detailed information.
Resources
License
MIT © Igor Suvorov
fishdash - Swimming in utilities 🐠
