The modern, community-first TypeScript toolkit with all of the fast, readable, and minimal utility functions you need. Type-safe, dependency-free, tree-shakeable, fully tested.
Add getOrInsert and getOrInsertComputed functions → PR #444
Access or initialize map entries without boilerplate branching. getOrInsert writes the provided value once, while getOrInsertComputed lazily creates an entry only when it is missing.
Works with both Map and WeakMap instances
Returns the stored entry so you can chain additional logic
Avoids unnecessary factory calls when a key already exists
Compare arrays with Object.is precision. isArrayEqual checks length and element identity, correctly handling tricky cases like NaN, sparse arrays, and the +0/-0 distinction.
Uses Object.is so NaN matches itself while +0 and -0 stay distinct
Short-circuits when lengths differ for a fast inequality check
Quickly compare collections without writing loops. isMapEqual uses isEqual to traverse nested values, while isSetEqual focuses on membership equality for reference types.
Checks map sizes first, then verifies each key/value pair deeply
Compares set entries via Set#has, perfect for shared object references or primitive values
Gives you targeted equality helpers instead of overloading isEqual
import * as _ from 'radashi'
const left = new Map([
['id', 1],
['tags', ['radashi', 'bench']],
])
const right = new Map([
['tags', ['radashi', 'bench']],
['id', 1],
])
_.isMapEqual(left, right) // => true
const user = { id: 1 }
_.isSetEqual(new Set([user]), new Set([user])) // => true
Add absoluteJitter and proportionalJitter functions → PR #446
Inject randomized noise into numbers for simulations, experiments, or simple variability. Choose an absolute range or a proportional factor depending on the use case.
absoluteJitter offsets the base value by up to ±offset
proportionalJitter scales jitter by a percentage of the base value
Designed for symmetric distributions using Math.random() under the hood
import * as _ from 'radashi'
const base = 100
_.absoluteJitter(base, 5) // => between 95 and 105
_.proportionalJitter(base, 0.1) // => between 90 and 110
Use identity as the default getter for sort→ PR #423
sort now handles raw numeric arrays without a custom getter. When you omit the getter, it falls back to identity, keeping the API ergonomic while preserving the ability to switch to descending order.
Explicitly pass _.identity when you want to sort descending
Still clones the array, leaving your original list untouched
Allow objectify callbacks to read the item index → PR #440
Both getKey and getValue callbacks now receive the item index, making it easy to build composite keys or inject positional data while converting arrays into dictionaries.
Keep keys unique by appending the index to collisions
Shape return values with both the item and its position
Works seamlessly with existing objectify call sites
Preserve tuple types when using min and max getters → PR #436
When you pass a getter to min or max, the helper now returns the original tuple element instead of widening to T | null. That keeps discriminated unions and as const tuples fully typed.
New overloads ensure non-empty tuples come back as the same literal type
Keeps null out of the result when the tuple has at least one item
Helps TypeScript infer richer shapes in downstream code
import * as _ from 'radashi'
const sizes = [
{ label: 'S', weight: 8 },
{ label: 'XL', weight: 12 },
] as const
const biggest = _.max(sizes, size => size.weight)
// biggest is non-nullable, since sizes is known to never be empty
Thanks to Nano Miratus for tightening up the typings!
Clarify that unique preserves original ordering → PR #433
The docs now state that unique keeps the first occurrence of each item. Examples and tests were updated to highlight the stable ordering and refreshed copy for clarity.
Explicitly documents that duplicates keep their earliest entry