@rimbu/deep 2.0.1 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +295 -60
  2. package/dist/bun/deep.mts +8 -8
  3. package/dist/bun/match.mts +29 -27
  4. package/dist/bun/patch.mts +11 -10
  5. package/dist/bun/path.mts +98 -100
  6. package/dist/bun/protected.mts +18 -17
  7. package/dist/bun/selector.mts +22 -20
  8. package/dist/bun/tuple.mts +6 -2
  9. package/dist/cjs/deep.cjs +18 -18
  10. package/dist/cjs/deep.cjs.map +1 -1
  11. package/dist/cjs/deep.d.cts +6 -6
  12. package/dist/cjs/match.cjs +2 -3
  13. package/dist/cjs/match.cjs.map +1 -1
  14. package/dist/cjs/match.d.cts +2 -2
  15. package/dist/cjs/patch.cjs +2 -3
  16. package/dist/cjs/patch.cjs.map +1 -1
  17. package/dist/cjs/patch.d.cts +1 -1
  18. package/dist/cjs/path.cjs +5 -5
  19. package/dist/cjs/path.cjs.map +1 -1
  20. package/dist/cjs/path.d.cts +8 -6
  21. package/dist/cjs/selector.cjs +1 -2
  22. package/dist/cjs/selector.cjs.map +1 -1
  23. package/dist/cjs/tuple.cjs +1 -1
  24. package/dist/cjs/tuple.cjs.map +1 -1
  25. package/dist/cjs/tuple.d.cts +5 -1
  26. package/dist/esm/deep.d.mts +6 -6
  27. package/dist/esm/deep.mjs +6 -6
  28. package/dist/esm/match.d.mts +2 -2
  29. package/dist/esm/match.mjs +1 -1
  30. package/dist/esm/match.mjs.map +1 -1
  31. package/dist/esm/patch.d.mts +1 -1
  32. package/dist/esm/patch.mjs +1 -1
  33. package/dist/esm/patch.mjs.map +1 -1
  34. package/dist/esm/path.d.mts +8 -6
  35. package/dist/esm/path.mjs +2 -2
  36. package/dist/esm/path.mjs.map +1 -1
  37. package/dist/esm/selector.mjs.map +1 -1
  38. package/dist/esm/tuple.d.mts +5 -1
  39. package/dist/esm/tuple.mjs +1 -1
  40. package/dist/esm/tuple.mjs.map +1 -1
  41. package/package.json +7 -7
  42. package/src/deep.mts +8 -8
  43. package/src/match.mts +29 -27
  44. package/src/patch.mts +11 -10
  45. package/src/path.mts +98 -100
  46. package/src/protected.mts +18 -17
  47. package/src/selector.mts +22 -20
  48. package/src/tuple.mts +6 -2
package/README.md CHANGED
@@ -1,112 +1,347 @@
1
1
  <p align="center">
2
- <img src="https://github.com/rimbu-org/rimbu/raw/main/assets/rimbu_logo.svg" />
2
+ <img src="https://github.com/rimbu-org/rimbu/raw/main/assets/rimbu_logo.svg" height="96" alt="Rimbu Logo" />
3
3
  </p>
4
4
 
5
- [![npm version](https://badge.fury.io/js/@rimbu%2Fdeep.svg)](https://www.npmjs.com/package/@rimbu/deep) [![Deno](https://shield.deno.dev/x/rimbu)](http://deno.land/x/rimbu)
5
+ <div align="center">
6
6
 
7
- ![Licence](https://img.shields.io/github/license/rimbu-org/rimbu)
7
+ [![npm version](https://badge.fury.io/js/@rimbu%2Fdeep.svg)](https://www.npmjs.com/package/@rimbu/deep)
8
+ ![License](https://img.shields.io/github/license/rimbu-org/rimbu)
9
+ ![Types Included](https://img.shields.io/badge/TypeScript-ready-blue)
10
+ ![Node](https://img.shields.io/badge/Node-18+-6DA55F?logo=node.js&logoColor=white)
11
+ ![Deno](https://shield.deno.dev/x/rimbu)
12
+ ![Bun](https://img.shields.io/badge/Bun-%23000000.svg)
13
+ ![ESM + CJS](https://img.shields.io/badge/modules-ESM%20%2B%20CJS-informational)
8
14
 
9
- # @rimbu/deep
15
+ </div>
10
16
 
11
- Offers tools to use handle plain JS objects as immutable objects. The [`Patch` object](https://rimbu.org/docs/deep/patch) allows convenient immutable modification of simple objects. The [`Match` object](https://rimbu.org/docs/deep/match) allows easy matching on plain objects. The [`Path` object](https://rimbu.org/docs/deep/path) allows easy querying of nested values. The [`Immutable` type](https://rimbu.org/docs/deep/immutable) makes it easy to create plain objects that that have compile-time protection against mutation. The [`Tuple` type](https://rimbu.org/docs/deep/tuple) is a utility to have similar functionality as `as const` but less strict.
17
+ # `@rimbu/deep`
12
18
 
13
- For complete documentation please visit the [Immutable Objects overview](https://rimbu.org/docs/deep/overview) in the _[Rimbu Docs](https://rimbu.org)_, or directly see the _[Rimbu Deep API Docs](https://rimbu.org/api/rimbu/deep)_.
19
+ **Immutable, type-safe utilities for deeply patching, matching, and selecting from plain JavaScript objects.**
14
20
 
15
- Or [Try Out Rimbu](https://codesandbox.io/s/github/vitoke/rimbu-sandbox/tree/main?previewwindow=console&view=split&editorsize=65&moduleview=1&module=/src/index.ts) in CodeSandBox.
21
+ `@rimbu/deep` gives you a set of composable tools – `Patch`, `Match`, `Path`, `Selector`, `Protected`, and `Tuple` –
22
+ to treat plain objects as if they were immutable, deeply typed data structures. You can:
16
23
 
17
- ## Installation
24
+ - **Apply immutable updates** to nested structures using a flexible `Patch` notation.
25
+ - **Express rich match conditions** over objects and arrays using `Match`.
26
+ - **Access nested properties safely** using type‑checked string `Path`s.
27
+ - **Build typed projections** from objects using `Selector` shapes.
28
+ - **Protect values at compile time** from accidental mutation using `Protected`.
29
+ - **Work ergonomically with tuples** and fixed‑length arrays via `Tuple`.
18
30
 
19
- ### Compabitity
31
+ Use it whenever you want the convenience of plain objects, but with **deep type safety**, **immutable semantics**, and
32
+ **refactor‑friendly string paths**.
20
33
 
21
- - [`Node >= 16` ![NodeJS](https://img.shields.io/badge/node.js-6DA55F?logo=node.js&logoColor=white)](https://nodejs.org)
22
- - [`Deno` ![Deno JS](https://img.shields.io/badge/deno%20js-000000?logo=deno&logoColor=white)](https://deno.com/runtime)
23
- - [`Bun >= 0.6.0` ![Bun](https://img.shields.io/badge/Bun-%23000000.svg?logoColor=white)](https://bun.sh/)
24
- - `Web` ![HTML5](https://img.shields.io/badge/html5-%23E34F26.svg?logoColor=white)
34
+ ---
25
35
 
26
- ### Yarn / NPM / Bun
36
+ ## Table of Contents
27
37
 
28
- For convenience, all main types are also exported through [`@rimbu/core`](../core).
38
+ 1. [Why `@rimbu/deep`?](#why-rimbu-deep)
39
+ 2. [Feature Highlights](#feature-highlights)
40
+ 3. [Quick Start](#quick-start)
41
+ 4. [Core Concepts & Types](#core-concepts--types)
42
+ 5. [Deep API Helpers](#deep-api-helpers)
43
+ 6. [Installation](#installation)
44
+ 7. [Ecosystem & Further Reading](#ecosystem--further-reading)
45
+ 8. [Contributing](#contributing)
46
+ 9. [License](#license)
29
47
 
30
- To install this package only:
48
+ ---
31
49
 
32
- For `yarn`:
50
+ ## Why `@rimbu/deep`?
33
51
 
34
- > `yarn add @rimbu/deep`
52
+ Plain objects are great, but they quickly become painful when:
35
53
 
36
- For `npm`:
54
+ - You need to **update nested fields immutably** (e.g. in Redux‑style state).
55
+ - You want **type‑safe string paths** like `'a.b.c[0]?.d'` instead of ad‑hoc helpers.
56
+ - You’d like to **pattern‑match** complex structures without a forest of `if`/`switch` checks.
57
+ - You want to **project and reshape data** (e.g. API responses) into well‑typed views.
37
58
 
38
- > `npm i @rimbu/deep`
59
+ `@rimbu/deep` focuses on:
39
60
 
40
- For `bun`:
61
+ - **Type‑driven paths and selectors** – `Path` and `Selector` are derived from your data types.
62
+ - **Immutable patching** – `Patch` lets you describe updates declaratively and apply them in one go.
63
+ - **Expressive matching** – `Match` supports nested objects, arrays, tuples, and compound predicates.
64
+ - **Compile‑time protection** – `Protected<T>` makes entire object graphs appear readonly to TypeScript.
41
65
 
42
- > `bun add @rimbu/deep`
66
+ If you find yourself writing a lot of manual cloning, deep property access, or matcher utilities, `@rimbu/deep` is a
67
+ drop‑in improvement.
43
68
 
44
- ### Deno
69
+ ---
45
70
 
46
- For Deno, the following approach is recommended:
71
+ ## Feature Highlights
47
72
 
48
- In the root folder of your project, create or edit a file called `import_map.json` with the following contents (where you should replace `x.y.z` with the desired version of Rimbu):
73
+ - **Deep immutable patching** with `patch` and `patchAt`:
74
+ describe updates using nested objects/arrays and functions instead of manual cloning.
75
+ - **Typed string paths** with `Path.Get` and `Path.Set`:
76
+ only valid paths for your data type compile.
77
+ - **Structured matching** with `match`:
78
+ supports nested objects, tuple/array traversal, and compound matchers (`every`, `some`, `none`, `single`).
79
+ - **Selection & projection** with `select` and `Selector`:
80
+ derive new shapes from existing data using path strings, functions, or nested selector objects.
81
+ - **Compile‑time protection** with `Protected` and `protect`:
82
+ make values deeply readonly at the type level while still using the underlying runtime value.
83
+ - **Tuple helpers** with `Tuple`:
84
+ ergonomics around fixed‑length tuples (construction, indexing, updates, etc.).
49
85
 
50
- ```json
51
- {
52
- "imports": {
53
- "@rimbu/": "https://deno.land/x/rimbu@x.y.z/"
54
- }
86
+ ---
87
+
88
+ ## Quick Start
89
+
90
+ ```ts
91
+ import { Deep } from '@rimbu/deep';
92
+
93
+ const input = { a: 1, b: { c: true, d: 'a' } } as const;
94
+
95
+ // Immutable deep patch
96
+ const updated = Deep.patch(input, [{ b: [{ c: (v) => !v }] }]);
97
+ // => { a: 1, b: { c: false, d: 'a' } }
98
+
99
+ // Type-safe nested get
100
+ const cValue = Deep.getAt(input, 'b.c'); // boolean
101
+
102
+ // Pattern matching
103
+ if (Deep.match(input, { b: { c: true } })) {
104
+ // ...
55
105
  }
106
+
107
+ // Selection / projection
108
+ const projected = Deep.select(input, { flag: 'b.c', label: 'b.d' });
109
+ // projected: { flag: boolean; label: string }
110
+ ```
111
+
112
+ Try Rimbu (including `@rimbu/deep`) live in the browser using the
113
+ [Rimbu Sandbox on CodeSandbox](https://codesandbox.io/s/github/vitoke/rimbu-sandbox/tree/main?previewwindow=console&view=split&editorsize=65&moduleview=1&module=/src/index.ts).
114
+
115
+ ---
116
+
117
+ ## Core Concepts & Types
118
+
119
+ ### Exported Types & Namespaces
120
+
121
+ From `@rimbu/deep`’s main entrypoint you have access to:
122
+
123
+ | Name | Description |
124
+ | ---------------------------- | -------------------------------------------------------------------------------------------------------- |
125
+ | `Patch<T, C = T>` | Type describing allowed patch shapes for a value of type `T`. |
126
+ | `Match<T, C = Partial<T>>` | Type describing allowed matchers for values of type `T`. |
127
+ | `Path` | Namespace containing `Path.Get<T>`, `Path.Set<T>`, and `Path.Result<T, P>` utilities for string paths. |
128
+ | `Selector<T>` | Type describing allowed selector shapes for values of type `T`. |
129
+ | `Protected<T>` | Deeply readonly/“protected” view of `T` for compile‑time mutation safety. |
130
+ | `Tuple<T extends Tuple.Source>` | Tuple wrapper with helper types and functions under the `Tuple` namespace. |
131
+ | `Deep` | Convenience namespace exposing the main deep utilities (`patch`, `match`, `getAt`, `select`, etc.). |
132
+
133
+ See the [Deep overview docs](https://rimbu.org/docs/deep/overview) and
134
+ [API reference](https://rimbu.org/api/rimbu/deep) for the full surface.
135
+
136
+ ### Patching with `patch` and `Patch`
137
+
138
+ ```ts
139
+ import { Deep, type Patch } from '@rimbu/deep';
140
+
141
+ type State = {
142
+ count: number;
143
+ user?: { name: string; active: boolean };
144
+ };
145
+
146
+ const state: State = { count: 1, user: { name: 'Ada', active: true } };
147
+
148
+ const patchItem: Patch<State> = [
149
+ { count: (v) => v + 1 },
150
+ { user: [{ active: false }] },
151
+ ];
152
+
153
+ const next = Deep.patch(state, patchItem);
154
+ // => { count: 2, user: { name: 'Ada', active: false } }
155
+ ```
156
+
157
+ Patches can be:
158
+
159
+ - Direct replacement values (`T`).
160
+ - Functions `(current, parent, root) => newValue`.
161
+ - Nested objects / arrays describing which fields or tuple indices to update.
162
+
163
+ ### Matching with `match` and `Match`
164
+
165
+ ```ts
166
+ import { Deep, type Match } from '@rimbu/deep';
167
+
168
+ type Item = { id: number; tags: string[] };
169
+
170
+ const items: Item[] = [
171
+ { id: 1, tags: ['a', 'b'] },
172
+ { id: 2, tags: ['b'] },
173
+ ];
174
+
175
+ const matcher: Match<Item> = {
176
+ tags: { someItem: (tag) => tag === 'a' },
177
+ };
178
+
179
+ const result = items.filter((item) => Deep.match(item, matcher));
180
+ // => only items containing tag 'a'
181
+ ```
182
+
183
+ `Match` supports:
184
+
185
+ - Plain object matchers (`{ a: 1, b: { c: true } }`).
186
+ - Function matchers `(value, parent, root) => boolean | matcher`.
187
+ - Array/tuple matchers and traversal helpers such as `someItem`, `everyItem`, `noneItem`, `singleItem`.
188
+ - Compound matchers like `['every', matcher1, matcher2]`.
189
+
190
+ ### Paths with `Path.Get`, `Path.Set` and `getAt` / `patchAt`
191
+
192
+ ```ts
193
+ import { Deep, type Path } from '@rimbu/deep';
194
+
195
+ type Model = { a: { b: { c: number }[] } };
196
+ const value: Model = { a: { b: { c: [5, 6] } } as any };
197
+
198
+ // Typed paths
199
+ const path: Path.Get<Model> = 'a.b.c[1]?.d'; // compile-time checked
200
+
201
+ // Reading
202
+ const result = Deep.getAt(value, 'a.b.c[0]'); // number | undefined
203
+
204
+ // Patching at a path
205
+ const updated = Deep.patchAt(value, 'a.b.c', (arr) => [...arr, 7]);
206
+ ```
207
+
208
+ `Path.Result<T, P>` gives you the resulting type at a given path `P` in `T`.
209
+
210
+ ### Selection with `Selector` and `select`
211
+
212
+ ```ts
213
+ import { Deep, type Selector } from '@rimbu/deep';
214
+
215
+ type Source = {
216
+ a: { b: number; c: string };
217
+ meta: { createdAt: string };
218
+ };
219
+
220
+ const source: Source = {
221
+ a: { b: 1, c: 'x' },
222
+ meta: { createdAt: '2024-01-01' },
223
+ };
224
+
225
+ const selector: Selector<Source> = {
226
+ value: 'a.b',
227
+ label: 'a.c',
228
+ created: 'meta.createdAt',
229
+ };
230
+
231
+ const view = Deep.select(source, selector);
232
+ // view: { value: number; label: string; created: string }
56
233
  ```
57
234
 
58
- **Note: The trailing slashes are important!**
235
+ Selectors can be:
236
+
237
+ - String paths.
238
+ - Functions `(value: Protected<T>) => any`.
239
+ - Arrays or objects composed of other selectors.
59
240
 
60
- In this way you can use relative imports from Rimbu in your code, like so:
241
+ ### Protection with `Protected` and `protect`
61
242
 
62
243
  ```ts
63
- import { List } from '@rimbu/core/mod.ts';
64
- import { HashMap } from '@rimbu/hashed/mod.ts';
244
+ import { Deep, type Protected } from '@rimbu/deep';
245
+
246
+ type Data = { a: { b: number[] } };
247
+
248
+ const data: Data = { a: { b: [1, 2] } };
249
+ const protectedData: Protected<Data> = Deep.protect(data);
250
+
251
+ // protectedData.a.b.push(3); // TypeScript error – `b` is readonly
65
252
  ```
66
253
 
67
- Note that for sub-packages, due to conversion limitations it is needed to import the `index.ts` instead of `mod.ts`, like so:
254
+ `Protected<T>` is a **type‑level** construct: it does not freeze the value at runtime, but helps prevent
255
+ accidental mutations in your code.
256
+
257
+ ---
258
+
259
+ ## Deep API Helpers
260
+
261
+ All top‑level utilities are also available through the `Deep` namespace:
68
262
 
69
263
  ```ts
70
- import { HashMap } from '@rimbu/hashed/map/index.ts';
264
+ import { Deep } from '@rimbu/deep';
265
+
266
+ // Functional helpers
267
+ const incCount = Deep.patchWith<{ count: number }>([{ count: (v) => v + 1 }]);
268
+ const onlyActive = Deep.matchWith({ active: true });
269
+ const getName = Deep.getAtWith<{ user: { name: string } }>('user.name');
270
+
271
+ // Typed, curried API with withType
272
+ const s = { a: 1, b: { c: 'a', d: true } };
273
+ const api = Deep.withType<typeof s>();
274
+
275
+ const next = api.patchWith([{ b: [{ d: (v) => !v }] }])(s);
276
+ // => { a: 1, b: { c: 'a', d: false } }
277
+ ```
278
+
279
+ The `Deep` namespace mirrors the main exports:
280
+
281
+ - `Deep.patch`, `Deep.patchAt`, `Deep.patchWith`, `Deep.patchAtWith`
282
+ - `Deep.match`, `Deep.matchAt`, `Deep.matchWith`, `Deep.matchAtWith`
283
+ - `Deep.getAt`, `Deep.getAtWith`
284
+ - `Deep.select`, `Deep.selectAt`, `Deep.selectWith`, `Deep.selectAtWith`
285
+ - `Deep.withType<T>()` for creating a typed, curried API.
286
+
287
+ ---
288
+
289
+ ## Installation
290
+
291
+ ### Node / Bun / npm / Yarn
292
+
293
+ ```sh
294
+ npm install @rimbu/deep
295
+ # or
296
+ yarn add @rimbu/deep
297
+ # or
298
+ bun add @rimbu/deep
71
299
  ```
72
300
 
73
- To run your script (let's assume the entry point is in `src/main.ts`):
301
+ ### Deno (import map)
74
302
 
75
- `deno run --import-map import_map.json src/main.ts`
303
+ ```jsonc
304
+ {
305
+ "imports": {
306
+ "@rimbu/": "https://deno.land/x/rimbu@<version>/"
307
+ }
308
+ }
309
+ ```
76
310
 
77
- ## Usage
311
+ Then:
78
312
 
79
313
  ```ts
80
- import { patch } from '@rimbu/deep';
81
-
82
- console.log(
83
- patch({
84
- a: 'a',
85
- b: { c: 1, d: true },
86
- })({
87
- a: 'q',
88
- b: { c: (v) => v + 1 },
89
- })
90
- );
91
- // => { a: 'q', b: { c: 2, d: true }}
314
+ import { Deep } from '@rimbu/deep/mod.ts';
92
315
  ```
93
316
 
94
- ## Author
317
+ ### Browser / ESM
95
318
 
96
- [Arvid Nicolaas](https://github.com/vitoke)
319
+ `@rimbu/deep` ships both **ESM** and **CJS** builds. Use it with any modern bundler
320
+ (Vite, Webpack, esbuild, Bun, etc.) or directly in Node ESM projects.
321
+
322
+ ---
323
+
324
+ ## Ecosystem & Further Reading
325
+
326
+ - Part of the broader **Rimbu** ecosystem – interoperates with `@rimbu/core`, `@rimbu/collection-types`,
327
+ and other collection packages.
328
+ - Ideal for modelling immutable application state, selectors, and matchers in complex domains.
329
+ - Learn more in the [Deep overview docs](https://rimbu.org/docs/deep/overview) and the
330
+ [Deep API reference](https://rimbu.org/api/rimbu/deep).
331
+
332
+ ---
97
333
 
98
334
  ## Contributing
99
335
 
100
- Feel very welcome to contribute to further improve Rimbu. Please read our [Contributing guide](https://github.com/rimbu-org/rimbu/blob/main/CONTRIBUTING.md).
336
+ We welcome contributions! See the
337
+ [Contributing guide](https://github.com/rimbu-org/rimbu/blob/main/CONTRIBUTING.md) for details.
101
338
 
102
- ## Contributors
339
+ <img src="https://contrib.rocks/image?repo=rimbu-org/rimbu" alt="Contributors" />
103
340
 
104
- <img src = "https://contrib.rocks/image?repo=rimbu-org/rimbu"/>
341
+ _Made with [contributors-img](https://contrib.rocks)._
105
342
 
106
- Made with [contributors-img](https://contrib.rocks).
343
+ ---
107
344
 
108
345
  ## License
109
346
 
110
- Licensed under the MIT License, Copyright © 2020-present Arvid Nicolaas.
111
-
112
- See [LICENSE](./LICENSE) for more information.
347
+ MIT © Rimbu contributors. See [LICENSE](./LICENSE) for details.
package/dist/bun/deep.mts CHANGED
@@ -90,9 +90,9 @@ export function patchAtWith<T, P extends Path.Set<T>, TE extends T = T, TT = T>(
90
90
 
91
91
  /**
92
92
  * Returns a function that matches a given `value` with the given `matcher`.
93
- * @typeparam T - the patch value type
93
+ * @typeparam T - the input value type
94
94
  * @param matcher - a matcher object that matches input values.
95
- * @param source - the value to use the given `patchItem` on at the given `path`.
95
+ * @param source - the value to match (parameter of the returned function).
96
96
  * @example
97
97
  * ```ts
98
98
  * const items = [{ a: 1, b: 'a' }, { a: 2, b: 'b' }];
@@ -128,7 +128,7 @@ export function matchAt<T, P extends Path.Get<T>>(
128
128
 
129
129
  /**
130
130
  * Returns a function that matches a given `value` with the given `matcher` at the given string `path`.
131
- * @typeparam T - the patch value type
131
+ * @typeparam T - the input value type
132
132
  * @typeparam P - the string literal path type in the object
133
133
  * @typeparam TE - utility type
134
134
  * @param path - the string path in the object
@@ -150,7 +150,7 @@ export function matchAtWith<T, P extends Path.Get<T>, TE extends T = T>(
150
150
 
151
151
  /**
152
152
  * Returns a function that selects a certain shape from a given `value` with the given `selector`.
153
- * @typeparam T - the patch value type
153
+ * @typeparam T - the input value type
154
154
  * @typeparam SL - the selector shape type
155
155
  * @param selector - a shape indicating the selection from the source values
156
156
  * @param source - the value to use the given `selector` on.
@@ -169,7 +169,7 @@ export function selectWith<T, SL extends Selector<T>>(
169
169
 
170
170
  /**
171
171
  * Returns the result of applying the given `selector` shape to the given `source` value.
172
- * @typeparam T - the patch value type
172
+ * @typeparam T - the input value type
173
173
  * @typeparam P - the string literal path type in the object
174
174
  * @typeparam SL - the selector shape type
175
175
  * @param source - the source value to select from
@@ -185,7 +185,7 @@ export function selectWith<T, SL extends Selector<T>>(
185
185
  export function selectAt<
186
186
  T,
187
187
  P extends Path.Get<T>,
188
- SL extends Selector<Path.Result<T, P>>
188
+ SL extends Selector<Path.Result<T, P>>,
189
189
  >(
190
190
  source: T,
191
191
  path: P,
@@ -196,7 +196,7 @@ export function selectAt<
196
196
 
197
197
  /**
198
198
  * Returns a function that selects a certain shape from a given `value` with the given `selector` at the given string `path`.
199
- * @typeparam T - the patch value type
199
+ * @typeparam T - the input value type
200
200
  * @typeparam P - the string literal path type in the object
201
201
  * @typeparam SL - the selector shape type
202
202
  * @param path - the string path in the object
@@ -211,7 +211,7 @@ export function selectAt<
211
211
  export function selectAtWith<
212
212
  T,
213
213
  P extends Path.Get<T>,
214
- SL extends Selector<Path.Result<T, P>>
214
+ SL extends Selector<Path.Result<T, P>>,
215
215
  >(
216
216
  path: P,
217
217
  selector: Selector.Shape<SL>
@@ -28,25 +28,31 @@ export namespace Match {
28
28
  * @typeparam P - the parent type
29
29
  * @typeparam R - the root object type
30
30
  */
31
- export type Entry<T, C, P, R> = IsAnyFunc<T> extends true
32
- ? // function can only be directly matched
33
- T
34
- : IsPlainObj<T> extends true
35
- ? // determine allowed match values for object
36
- Match.WithResult<T, P, R, Match.Obj<T, C, P, R>>
37
- : IsArray<T> extends true
38
- ? // determine allowed match values for array or tuple
39
- | Match.Arr<T, C, P, R>
40
- | Match.Entry<T[number & keyof T], C[number & keyof C], P, R>[]
41
- | Match.Func<
42
- T,
43
- P,
44
- R,
31
+ export type Entry<T, C, P, R> =
32
+ IsAnyFunc<T> extends true
33
+ ? // function can only be directly matched
34
+ T
35
+ : IsPlainObj<T> extends true
36
+ ? // determine allowed match values for object
37
+ Match.WithResult<T, P, R, Match.Obj<T, C, P, R>>
38
+ : IsArray<T> extends true
39
+ ? // determine allowed match values for array or tuple
45
40
  | Match.Arr<T, C, P, R>
46
- | Match.Entry<T[number & keyof T], C[number & keyof C], P, R>[]
47
- >
48
- : // only accept values with same interface
49
- Match.WithResult<T, P, R, { [K in keyof C]: C[K & keyof T] }>;
41
+ | Match.Entry<T[number & keyof T], C[number & keyof C], P, R>[]
42
+ | Match.Func<
43
+ T,
44
+ P,
45
+ R,
46
+ | Match.Arr<T, C, P, R>
47
+ | Match.Entry<
48
+ T[number & keyof T],
49
+ C[number & keyof C],
50
+ P,
51
+ R
52
+ >[]
53
+ >
54
+ : // only accept values with same interface
55
+ Match.WithResult<T, P, R, { [K in keyof C]: C[K & keyof T] }>;
50
56
 
51
57
  /**
52
58
  * The type that determines allowed matchers for objects.
@@ -128,7 +134,7 @@ export namespace Match {
128
134
  export type ArrayTraversalType = `${CompoundType}Item`;
129
135
 
130
136
  /**
131
- * Compount matcher for objects, can only be an array staring with a compound type keyword.
137
+ * Compound matcher for objects, represented as an array starting with a compound type keyword.
132
138
  * @typeparam T - the input value type
133
139
  * @typeparam C - utility type
134
140
  * @typeparam P - the parent type
@@ -136,7 +142,7 @@ export namespace Match {
136
142
  */
137
143
  export type CompoundForObj<T, C, P, R> = [
138
144
  Match.CompoundType,
139
- ...Match.Entry<T, C, P, R>[]
145
+ ...Match.Entry<T, C, P, R>[],
140
146
  ];
141
147
 
142
148
  /**
@@ -188,7 +194,7 @@ export namespace Match {
188
194
  * match(input, { a: 2 }) // => false
189
195
  * match(input, { a: (v) => v > 10 }) // => false
190
196
  * match(input, { b: { c: true }}) // => true
191
- * match(input, (['every', { a: (v) => v > 0 }, { b: { c: true } }]) // => true
197
+ * match(input, ['every', { a: (v) => v > 0 }, { b: { c: true } }]) // => true
192
198
  * match(input, { b: { c: (v, parent, root) => v && parent.d.length > 0 && root.a > 0 } })
193
199
  * // => true
194
200
  * ```
@@ -272,9 +278,7 @@ function matchEntry<T, C, P, R>(
272
278
  // already determined above that the source and matcher are not equal
273
279
 
274
280
  failureLog?.push(
275
- `value ${JSON.stringify(
276
- source
277
- )} does not match given matcher ${JSON.stringify(matcher)}`
281
+ `value ${JSON.stringify(source)} does not match given matcher ${JSON.stringify(matcher)}`
278
282
  );
279
283
 
280
284
  return false;
@@ -469,9 +473,7 @@ function matchPlainObj<T extends object, C, P, R>(
469
473
  // the source does not have the given key
470
474
 
471
475
  failureLog?.push(
472
- `key ${key} is specified in matcher but not present in value ${JSON.stringify(
473
- source
474
- )}`
476
+ `key ${key} is specified in matcher but not present in value ${JSON.stringify(source)}`
475
477
  );
476
478
 
477
479
  return false;
@@ -22,15 +22,16 @@ export namespace Patch {
22
22
  * @typeparam P - the parent type
23
23
  * @typeparam R - the root object type
24
24
  */
25
- export type Entry<T, C, P, R> = IsAnyFunc<T> extends true
26
- ? T
27
- : IsPlainObj<T> extends true
28
- ? Patch.WithResult<T, P, R, Patch.Obj<T, C, R>>
29
- : Tuple.IsTuple<T> extends true
30
- ? Patch.WithResult<T, P, R, T | Patch.Tup<T, C, R>>
31
- : IsArray<T> extends true
32
- ? Patch.WithResult<T, P, R, T>
33
- : Patch.WithResult<T, P, R, T>;
25
+ export type Entry<T, C, P, R> =
26
+ IsAnyFunc<T> extends true
27
+ ? T
28
+ : IsPlainObj<T> extends true
29
+ ? Patch.WithResult<T, P, R, Patch.Obj<T, C, R>>
30
+ : Tuple.IsTuple<T> extends true
31
+ ? Patch.WithResult<T, P, R, T | Patch.Tup<T, C, R>>
32
+ : IsArray<T> extends true
33
+ ? Patch.WithResult<T, P, R, T>
34
+ : Patch.WithResult<T, P, R, T>;
34
35
 
35
36
  /**
36
37
  * Either result type S, or a patch function with the value type, the parent type, and the root type.
@@ -109,7 +110,7 @@ export namespace Patch {
109
110
  * patch(input, [{ a: 2 }]) // => { a: 2, b: { c: true, d: 'a' } }
110
111
  * patch(input, [{ b: [{ c: (v) => !v }] }] )
111
112
  * // => { a: 1, b: { c: false, d: 'a' } }
112
- * patch(input: [{ a: (v) => v + 1, b: [{ d: 'q' }] }] )
113
+ * patch(input, [{ a: (v) => v + 1, b: [{ d: 'q' }] }] )
113
114
  * // => { a: 2, b: { c: true, d: 'q' } }
114
115
  * ```
115
116
  */