|
1 | | -## New Functions |
2 | | - |
3 | | -### Add `getOrInsert` and `getOrInsertComputed` functions [→ PR #444](https://github.com/radashi-org/radashi/pull/444) |
4 | | - |
5 | | -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. |
6 | | - |
7 | | -- Works with both `Map` and `WeakMap` instances |
8 | | -- Returns the stored entry so you can chain additional logic |
9 | | -- Avoids unnecessary factory calls when a key already exists |
10 | | - |
11 | | -```typescript |
12 | | -import * as _ from 'radashi' |
13 | | - |
14 | | -const counts = new Map<string, number>() |
15 | | - |
16 | | -_.getOrInsert(counts, 'clicks', 1) // => 1 |
17 | | -_.getOrInsert(counts, 'clicks', 5) // => 1 |
18 | | -_.getOrInsertComputed(counts, 'views', () => 10) // => 10 |
19 | | -_.getOrInsertComputed(counts, 'views', () => 0) // => 10 |
20 | | -``` |
21 | | - |
22 | | -Inspired by TC39's [upsert proposal](https://github.com/tc39/proposal-upsert). |
23 | | - |
24 | | -🔗 Docs: [getOrInsert](https://radashi.js.org/reference/object/getOrInsert) · [getOrInsertComputed](https://radashi.js.org/reference/object/getOrInsertComputed) / Source: [getOrInsert.ts](https://github.com/radashi-org/radashi/blob/main/src/object/getOrInsert.ts) · [getOrInsertComputed.ts](https://github.com/radashi-org/radashi/blob/main/src/object/getOrInsertComputed.ts) / Tests: [getOrInsert.test.ts](https://github.com/radashi-org/radashi/blob/main/tests/object/getOrInsert.test.ts) · [getOrInsertComputed.test.ts](https://github.com/radashi-org/radashi/blob/main/tests/object/getOrInsertComputed.test.ts) |
25 | | - |
26 | | -### Add `isArrayEqual` function [→ PR #417](https://github.com/radashi-org/radashi/pull/417) |
27 | | - |
28 | | -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. |
29 | | - |
30 | | -- Uses `Object.is` so `NaN` matches itself while `+0` and `-0` stay distinct |
31 | | -- Short-circuits when lengths differ for a fast inequality check |
32 | | -- Leaves the original arrays untouched |
33 | | - |
34 | | -```typescript |
35 | | -import * as _ from 'radashi' |
36 | | - |
37 | | -_.isArrayEqual([1, 2, 3], [1, 2, 3]) // => true |
38 | | -_.isArrayEqual([0], [-0]) // => false |
39 | | -_.isArrayEqual([Number.NaN], [Number.NaN]) // => true |
40 | | -``` |
41 | | - |
42 | | -🔗 [Docs](https://radashi.js.org/reference/array/isArrayEqual) / [Source](https://github.com/radashi-org/radashi/blob/main/src/array/isArrayEqual.ts) / [Tests](https://github.com/radashi-org/radashi/blob/main/tests/array/isArrayEqual.test.ts) |
43 | | - |
44 | | -### Add `isMapEqual` and `isSetEqual` functions [→ PR #437](https://github.com/radashi-org/radashi/pull/437) |
45 | | - |
46 | | -Quickly compare collections without writing loops. `isMapEqual` uses `isEqual` to traverse nested values, while `isSetEqual` focuses on membership equality for reference types. |
47 | | - |
48 | | -- Checks map sizes first, then verifies each key/value pair deeply |
49 | | -- Compares set entries via `Set#has`, perfect for shared object references or primitive values |
50 | | -- Gives you targeted equality helpers instead of overloading `isEqual` |
51 | | - |
52 | | -```typescript |
53 | | -import * as _ from 'radashi' |
54 | | - |
55 | | -const left = new Map([ |
56 | | - ['id', 1], |
57 | | - ['tags', ['radashi', 'bench']], |
58 | | -]) |
59 | | -const right = new Map([ |
60 | | - ['tags', ['radashi', 'bench']], |
61 | | - ['id', 1], |
62 | | -]) |
63 | | - |
64 | | -_.isMapEqual(left, right) // => true |
65 | | - |
66 | | -const user = { id: 1 } |
67 | | -_.isSetEqual(new Set([user]), new Set([user])) // => true |
68 | | -``` |
69 | | - |
70 | | -🔗 Docs: [isMapEqual](https://radashi.js.org/reference/typed/isMapEqual) · [isSetEqual](https://radashi.js.org/reference/typed/isSetEqual) / Source: [isMapEqual.ts](https://github.com/radashi-org/radashi/blob/main/src/typed/isMapEqual.ts) · [isSetEqual.ts](https://github.com/radashi-org/radashi/blob/main/src/typed/isSetEqual.ts) / Tests: [isMapEqual.test.ts](https://github.com/radashi-org/radashi/blob/main/tests/typed/isMapEqual.test.ts) · [isSetEqual.test.ts](https://github.com/radashi-org/radashi/blob/main/tests/typed/isSetEqual.test.ts) |
71 | | - |
72 | | -### Add `absoluteJitter` and `proportionalJitter` functions [→ PR #446](https://github.com/radashi-org/radashi/pull/446) |
73 | | - |
74 | | -Inject randomized noise into numbers for simulations, experiments, or simple variability. Choose an absolute range or a proportional factor depending on the use case. |
75 | | - |
76 | | -- `absoluteJitter` offsets the base value by up to ±`offset` |
77 | | -- `proportionalJitter` scales jitter by a percentage of the base value |
78 | | -- Designed for symmetric distributions using `Math.random()` under the hood |
79 | | - |
80 | | -```typescript |
81 | | -import * as _ from 'radashi' |
82 | | - |
83 | | -const base = 100 |
84 | | -_.absoluteJitter(base, 5) // => between 95 and 105 |
85 | | -_.proportionalJitter(base, 0.1) // => between 90 and 110 |
86 | | -``` |
87 | | - |
88 | | -🔗 Docs: [absoluteJitter](https://radashi.js.org/reference/random/absoluteJitter) · [proportionalJitter](https://radashi.js.org/reference/random/proportionalJitter) / Source: [absoluteJitter.ts](https://github.com/radashi-org/radashi/blob/main/src/random/absoluteJitter.ts) · [proportionalJitter.ts](https://github.com/radashi-org/radashi/blob/main/src/random/proportionalJitter.ts) / Tests: [absoluteJitter.test.ts](https://github.com/radashi-org/radashi/blob/main/tests/random/absoluteJitter.test.ts) · [proportionalJitter.test.ts](https://github.com/radashi-org/radashi/blob/main/tests/random/proportionalJitter.test.ts) |
89 | | - |
90 | | -### Add `identity` function [→ PR #422](https://github.com/radashi-org/radashi/pull/422) |
91 | | - |
92 | | -The `identity` helper simply returns the value you pass in, providing a lightweight default callback for APIs that expect a mapper function. |
93 | | - |
94 | | -- Fully generic, so TypeScript infers the original value type |
95 | | -- Handy as a default getter when working with utilities like `sort` |
96 | | -- Works even when no argument is supplied, returning `undefined` |
97 | | - |
98 | | -```typescript |
99 | | -import * as _ from 'radashi' |
| 1 | +If you open a PR that introduces a new function, add it to the "New Functions" section. If you're extending an existing function, add it to the "New Features" section. |
100 | 2 |
|
101 | | -_.identity() // => undefined |
102 | | -_.identity('radashi') // => 'radashi' |
103 | | -_.identity({ id: 1 }) // => { id: 1 } |
104 | | -``` |
| 3 | +The `####` headline should be short and descriptive of the new functionality. In the body of the section, include a link to the PR. You don't need to include a description of the change itself, as we will extract that from the documentation. |
105 | 4 |
|
106 | | -Thanks to [Nano Miratus](https://github.com/nnmrts) for adding this functional building block! |
| 5 | +## New Functions |
107 | 6 |
|
108 | | -🔗 [Docs](https://radashi.js.org/reference/function/identity) / [Source](https://github.com/radashi-org/radashi/blob/main/src/function/identity.ts) / [Tests](https://github.com/radashi-org/radashi/blob/main/tests/function/identity.test.ts) |
| 7 | +#### |
109 | 8 |
|
110 | 9 | ## New Features |
111 | 10 |
|
112 | | -### Use `identity` as the default getter for `sort` [→ PR #423](https://github.com/radashi-org/radashi/pull/423) |
113 | | - |
114 | | -`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. |
115 | | - |
116 | | -- Explicitly pass `_.identity` when you want to sort descending |
117 | | -- Still clones the array, leaving your original list untouched |
118 | | - |
119 | | -```typescript |
120 | | -import * as _ from 'radashi' |
121 | | - |
122 | | -const numbers = [2, 0, 1] |
123 | | - |
124 | | -_.sort(numbers) // => [0, 1, 2] |
125 | | -_.sort(numbers, _.identity, true) // => [2, 1, 0] |
126 | | -``` |
127 | | - |
128 | | -Thanks to [Nano Miratus](https://github.com/nnmrts) for smoothing out this API! |
129 | | - |
130 | | -🔗 [Docs](https://radashi.js.org/reference/array/sort) / [Source](https://github.com/radashi-org/radashi/blob/main/src/array/sort.ts) / [Tests](https://github.com/radashi-org/radashi/blob/main/tests/array/sort.test.ts) |
131 | | - |
132 | | -### Allow `objectify` callbacks to read the item index [→ PR #440](https://github.com/radashi-org/radashi/pull/440) |
133 | | - |
134 | | -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. |
135 | | - |
136 | | -- Keep keys unique by appending the index to collisions |
137 | | -- Shape return values with both the item and its position |
138 | | -- Works seamlessly with existing `objectify` call sites |
139 | | - |
140 | | -```typescript |
141 | | -import * as _ from 'radashi' |
142 | | - |
143 | | -const list = [ |
144 | | - { id: 'a', word: 'hello' }, |
145 | | - { id: 'b', word: 'bye' }, |
146 | | -] |
147 | | - |
148 | | -_.objectify( |
149 | | - list, |
150 | | - (item, i) => `${item.id}_${i}`, |
151 | | - (item, i) => `${item.word}-${i}`, |
152 | | -) |
153 | | -// => { a_0: 'hello-0', b_1: 'bye-1' } |
154 | | -``` |
155 | | - |
156 | | -Thanks to Ronen Barzel for extending `objectify`! |
157 | | - |
158 | | -🔗 [Docs](https://radashi.js.org/reference/array/objectify) / [Source](https://github.com/radashi-org/radashi/blob/main/src/array/objectify.ts) / [Tests](https://github.com/radashi-org/radashi/blob/main/tests/array/objectify.test.ts) |
159 | | - |
160 | | -### Preserve tuple types when using `min` and `max` getters [→ PR #436](https://github.com/radashi-org/radashi/pull/436) |
161 | | - |
162 | | -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. |
163 | | - |
164 | | -- New overloads ensure non-empty tuples come back as the same literal type |
165 | | -- Keeps `null` out of the result when the tuple has at least one item |
166 | | -- Helps TypeScript infer richer shapes in downstream code |
167 | | - |
168 | | -```typescript |
169 | | -import * as _ from 'radashi' |
170 | | - |
171 | | -const sizes = [ |
172 | | - { label: 'S', weight: 8 }, |
173 | | - { label: 'XL', weight: 12 }, |
174 | | -] as const |
175 | | - |
176 | | -const biggest = _.max(sizes, size => size.weight) |
177 | | -// biggest is inferred as { label: 'XL'; weight: 12 } |
178 | | -``` |
179 | | - |
180 | | -Thanks to [Nano Miratus](https://github.com/nnmrts) for tightening up the typings! |
181 | | - |
182 | | -🔗 Source: [max.ts](https://github.com/radashi-org/radashi/blob/main/src/number/max.ts) · [min.ts](https://github.com/radashi-org/radashi/blob/main/src/number/min.ts) |
183 | | - |
184 | | -## Documentation |
185 | | - |
186 | | -### Clarify that `unique` preserves original ordering [→ PR #433](https://github.com/radashi-org/radashi/pull/433) |
187 | | - |
188 | | -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. |
189 | | - |
190 | | -- Explicitly documents that duplicates keep their earliest entry |
191 | | -- Updates the example data to match the behavior |
192 | | -- Adds a unit test covering order preservation |
193 | | - |
194 | | -```typescript |
195 | | -import * as _ from 'radashi' |
196 | | - |
197 | | -const fish = [ |
198 | | - { name: 'Trout', source: 'lake' }, |
199 | | - { name: 'Salmon', source: 'stream' }, |
200 | | - { name: 'Salmon', source: 'river' }, |
201 | | -] |
202 | | - |
203 | | -_.unique(fish, item => item.name) |
204 | | -// => [Trout, Salmon] |
205 | | -``` |
206 | | - |
207 | | -Thanks to Ronen Barzel for polishing the documentation! |
208 | | - |
209 | | -🔗 [Docs](https://radashi.js.org/reference/array/unique) / [Tests](https://github.com/radashi-org/radashi/blob/main/tests/array/unique.test.ts) |
| 11 | +#### |
0 commit comments