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.
npm install supergeneric
// 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'
Version 4.x includes several breaking changes and optimizations:
-
getMilliseconds()
- Duration string parsing function has been removed -
console
- Color-injected console object has been removed
-
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
-
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:
- 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
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.
Returns the sum of all values in the array.
sum([1, 2, 3, 4]) // 10
Returns the arithmetic mean of all values.
average([1, 2, 3, 4]) // 2.5
Alias for average()
. Returns the arithmetic mean.
mean([1, 2, 3, 4]) // 2.5
Returns the smallest value. Optimized for large arrays.
min([7, 1, 4, 2]) // 1
Returns the largest value. Optimized for large arrays.
max([7, 1, 4, 2]) // 7
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 }
Returns the standard deviation using the sample formula (n-1).
stddev([1, 2, 3, 4, 5]) // 1.5811388300841898
Rounds a number to the specified decimal places (default: 0).
round(3.14159) // 3
round(3.14159, 2) // 3.14
Returns a curried rounding function with preset precision.
const roundTo2 = rounder(2)
[3.14159, 2.71828].map(roundTo2) // [3.14, 2.72]
Returns the first element of an array.
first([1, 2, 3]) // 1
first([]) // undefined
Returns the last element of an array.
last([1, 2, 3]) // 3
last([]) // undefined
Comparator function for ascending sort.
[3, 1, 4, 1, 5].sort(ascending) // [1, 1, 3, 4, 5]
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 length
Creates an array of sequential numbers.
range(5) // [0, 1, 2, 3, 4]
range(3, { from: 5 }) // [5, 6, 7]
Transposes a 2D array (swaps rows and columns).
transpose([[1, 2], [3, 4], [5, 6]]) // [[1, 3, 5], [2, 4, 6]]
Filters an array to only numeric values.
onlyNumbers([1, 'hello', 2.5, null, 42]) // [1, 2.5, 42]
Returns a random integer between min and max (inclusive).
random(1, 6) // 4 (dice roll)
random(10, 20) // 15
Returns a random element from an array or character from a string.
randomItem([1, 2, 3, 4, 5]) // 3
randomItem('hello') // 'e'
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]
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
})
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 }
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'
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')
Merges multiple objects into one.
merge({ a: 1 }, { b: 2 }, { c: 3 }) // { a: 1, b: 2, c: 3 }
Merges objects and removes undefined properties.
mergeClean({ a: 1, b: undefined }, { c: 3 }) // { a: 1, c: 3 }
Converts a value to a number if possible, otherwise returns unchanged.
['1', '2.5', 'hello', 3].map(numbers) // [1, 2.5, 'hello', 3]
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
Applies multiple transformation functions to data recursively.
const data = { values: ['1', '2', '3'] }
convert(data, numbers) // { values: [1, 2, 3] }
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] } }
All functions include full TypeScript definitions with proper generic types where applicable. The library is built with TypeScript and provides excellent IntelliSense support.
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'
- 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
MIT