supergeneric
A collection of lightweight, tree-shakable TypeScript utility functions for mathematical operations, array manipulation, object handling, and more. Designed for modern JavaScript/TypeScript projects with full type safety.
Installation
npm install supergenericUsage
// Import individual functions (recommended for tree-shaking)
import { sum, average, sortBy } from 'supergeneric'
// Or import specific functions directly
import { sum } from 'supergeneric/sum'
import { sortBy } from 'supergeneric/sortBy'Migrating from v3.x to v4.x
Version 4.x includes several breaking changes and optimizations:
🗑️ Removed Functions
getMilliseconds()- Duration string parsing function has been removedconsole- Color-injected console object has been removed
⚡ Performance Improvements
min()andmax()- No longer use spread operator (Math.min(...values)), now use optimized loops- Why: Fixes "Maximum call stack size exceeded" errors on large arrays (>100k elements)
- Impact: More reliable for large datasets, slightly larger bundle size (+30B gzipped each)
- Migration: No code changes needed, functions work identically but handle large arrays better
🔧 API Changes
min()andmax()- Now handle empty arrays consistently with other math functions- Before:
min([])would returnInfinity,max([])would return-Infinity - After:
min([])andmax([])returnundefined(following the same pattern asfirst()andlast())
- Before:
📦 Bundle Size Optimizations
- Code-golfed optimizations applied across all functions for smaller bundle sizes
- Bitwise operations used where appropriate (
>>instead ofMath.floor,&instead of%) - Eliminated unnecessary intermediate variables and redundant operations
🎯 Migration Guide
If you were using removed functions:
// v3.x - REMOVED in v4.x
import { getMilliseconds, console } from 'supergeneric'
// v4.x - Use alternatives
// For getMilliseconds: Use a dedicated duration parsing library like 'itty-time' or 'ms'
import ms from 'itty-time'
ms('1 hour') // 3600000
// For colored console: Use libraries like 'chalk' or 'kleur'
import chalk from 'chalk'
console.log(chalk.blue('Hello'))For large array handling (automatic improvement):
// v3.x - Could fail on large arrays
const largeArray = Array(200000).fill(0).map((_, i) => i)
min(largeArray) // RangeError: Maximum call stack size exceeded
// v4.x - Works reliably
min(largeArray) // 0 (no errors)All other functions remain backward compatible with the same APIs.
API Reference
📊 Mathematical Functions
sum(values: number[]): number
Returns the sum of all values in the array.
sum([1, 2, 3, 4]) // 10average(values: number[]): number
Returns the arithmetic mean of all values.
average([1, 2, 3, 4]) // 2.5mean(values: number[]): number
Alias for average(). Returns the arithmetic mean.
mean([1, 2, 3, 4]) // 2.5min(values: number[]): number
Returns the smallest value. Optimized for large arrays.
min([7, 1, 4, 2]) // 1max(values: number[]): number
Returns the largest value. Optimized for large arrays.
max([7, 1, 4, 2]) // 7median(values: any[], sortBy?: (a: any, b: any) => number): any
Returns the median value from an array.
median([1, 2, 3, 4, 5]) // 3
median([1, 2, 3, 4]) // 2.5
// With custom comparator
const items = [{ value: 3 }, { value: 1 }, { value: 4 }]
median(items, (a, b) => a.value - b.value) // { value: 3 }stddev(values: number[]): number
Returns the standard deviation using the sample formula (n-1).
stddev([1, 2, 3, 4, 5]) // 1.5811388300841898round(value: number, precision?: number): number
Rounds a number to the specified decimal places (default: 0).
round(3.14159) // 3
round(3.14159, 2) // 3.14rounder(precision?: number): (value: number) => number
Returns a curried rounding function with preset precision.
const roundTo2 = rounder(2)
[3.14159, 2.71828].map(roundTo2) // [3.14, 2.72]🔀 Array Functions
first<T>(values: T[]): T | undefined
Returns the first element of an array.
first([1, 2, 3]) // 1
first([]) // undefinedlast<T>(values: T[]): T | undefined
Returns the last element of an array.
last([1, 2, 3]) // 3
last([]) // undefinedascending<T>(a: T, b: T): number
Comparator function for ascending sort.
[3, 1, 4, 1, 5].sort(ascending) // [1, 1, 3, 4, 5]descending<T>(a: T, b: T): number
Comparator function for descending sort.
[3, 1, 4, 1, 5].sort(descending) // [5, 4, 3, 1, 1]sortBy<T>(key: keyof T | ((item: T) => any), options?: { descending?: boolean }): (a: T, b: T) => number
Creates a comparator function for sorting by property or extractor function.
const users = [
{ name: 'Alice', age: 30 },
{ name: 'Bob', age: 25 },
{ name: 'Carol', age: 35 }
]
// Sort by property
users.sort(sortBy('age')) // sorted by age ascending
users.sort(sortBy('name', { descending: true })) // by name descending
// Sort by function
users.sort(sortBy(u => u.name.length)) // by name lengthrange(length?: number, options?: { from?: number }): number[]
Creates an array of sequential numbers.
range(5) // [0, 1, 2, 3, 4]
range(3, { from: 5 }) // [5, 6, 7]transpose<T>(matrix: T[][]): T[][]
Transposes a 2D array (swaps rows and columns).
transpose([[1, 2], [3, 4], [5, 6]]) // [[1, 3, 5], [2, 4, 6]]onlyNumbers(values: any[]): number[]
Filters an array to only numeric values.
onlyNumbers([1, 'hello', 2.5, null, 42]) // [1, 2.5, 42]🎲 Random Functions
random(min: number, max: number): number
Returns a random integer between min and max (inclusive).
random(1, 6) // 4 (dice roll)
random(10, 20) // 15randomItem<T>(items: T[] | string): T | string
Returns a random element from an array or character from a string.
randomItem([1, 2, 3, 4, 5]) // 3
randomItem('hello') // 'e'randomArray(length?: number, fn?: () => any): any[]
Creates an array filled with results from a function.
randomArray(3) // [0.234, 0.789, 0.456] (random numbers)
randomArray(3, () => random(1, 10)) // [7, 2, 9]generateHash(length?: number, options?: GenerateHashOptions): string
Generates a random alphanumeric string with extensive customization options.
generateHash() // 'aB3kL9' (6 chars, starts with letter)
generateHash(8) // 'mK2pQ7R4'
// Advanced options
generateHash(10, {
startWithLetter: false,
ambiguous: false, // excludes similar-looking chars
symbols: '!@#',
only: 'ABCDEF123' // custom character set
})🔧 Utility Functions
binarySearch<T>(values: T[], by?: (item: T) => any): (target: any) => { item: T; index: number } | undefined
Performs binary search on a sorted array. Returns a search function.
const numbers = [1, 3, 5, 7, 9, 11]
const search = binarySearch(numbers)
search(5) // { item: 5, index: 2 }
search(4) // undefined
// With extractor function
const items = [{ id: 1 }, { id: 3 }, { id: 5 }]
const searchById = binarySearch(items, item => item.id)
searchById(3) // { item: { id: 3 }, index: 1 }makePath(...segments: any[]): string
Joins path segments with '/' delimiter, handling empty values and duplicates.
makePath('users', 42, 'profile') // 'users/42/profile'
makePath('api/', undefined, 'v1') // 'api/v1'
// Custom delimiter
makePath('a', 'b', 'c', { delimiter: '.' }) // 'a.b.c'required(message: string): never
Throws an error with the given message. Useful for required parameters.
function greet(name = required('name is required')) {
return `Hello, ${name}!`
}
greet('Alice') // 'Hello, Alice!'
greet() // throws: Error('name is required')🗃️ Object Functions
merge(...objects: object[]): object
Merges multiple objects into one.
merge({ a: 1 }, { b: 2 }, { c: 3 }) // { a: 1, b: 2, c: 3 }mergeClean(...objects: object[]): object
Merges objects and removes undefined properties.
mergeClean({ a: 1, b: undefined }, { c: 3 }) // { a: 1, c: 3 }numbers(value: any): any
Converts a value to a number if possible, otherwise returns unchanged.
['1', '2.5', 'hello', 3].map(numbers) // [1, 2.5, 'hello', 3]dates(obj: any, key: string): any
Converts date-like properties to Date objects.
const data = { created_at: '2023-01-01', updated_time: '2023-12-31' }
// Use with recurse() to process nested objects🔄 Data Transformation
convert(data: any, ...fns: Function[]): any
Applies multiple transformation functions to data recursively.
const data = { values: ['1', '2', '3'] }
convert(data, numbers) // { values: [1, 2, 3] }recurse(fn: Function): (data: any) => any
Creates a function that applies a transformation recursively to nested data.
const deepNumbers = recurse(numbers)
deepNumbers({
a: '1',
b: { c: '2', d: ['3', '4'] }
}) // { a: 1, b: { c: 2, d: [3, 4] } }TypeScript Support
All functions include full TypeScript definitions with proper generic types where applicable. The library is built with TypeScript and provides excellent IntelliSense support.
Tree Shaking
Import only the functions you need for optimal bundle size:
// Only imports the sum function
import { sum } from 'supergeneric'
// Or import directly for maximum tree-shaking
import { sum } from 'supergeneric/sum'Performance
- Mathematical functions use optimized loops instead of spread operators for large arrays
- Binary search provides O(log n) performance for sorted data
- All functions are pure and side-effect free where possible
License
MIT