getUpdates()function
Decode the prop updates in an Updates object into a set of Update objects.
getUpdates(data: Updates<T>): ImmutableArray<Update>
Updates<T> is the mutation language for Shelving data objects. An updates object uses encoded key prefixes to describe how each field should change — set, increment, or add/remove array items — and updateData() applies those changes immutably. This is the format consumed by the shelving/db layer when writing documents.
Things to know:
updateData() returns the same reference when no property actually changes, making it safe for equality checks and memoisation."=user.name" targets data.user.name.+= or -= target field is not already a number, the increment value becomes the new value.+[] target field is not already an array, the value(s) become the new array.getUpdates() parses an Updates object into an array of structured Update objects — useful when you need to inspect or forward updates programmatically.| Key syntax | Action |
|---|---|
key or =key | Set field to value |
+=key | Increment number |
-=key | Decrement number |
+[]key | Add item(s) to array |
-[]key | Remove item(s) from array |
Use plain key for most sets. Use =key when TypeScript inference gets confused by deeply-nested paths — the = prefix forces leaf-only matching and is more precise.
import { updateData } from "shelving/util";
const doc = { title: "Draft", count: 5, tags: ["a", "b"] };
updateData(doc, { title: "Published" }); // { title: "Published", count: 5, tags: [...] }
updateData(doc, { "=title": "Final" }); // same effect, more precise
updateData(doc, { "+=count": 3 }); // { ..., count: 8, ... }
updateData(doc, { "-=count": 1 }); // { ..., count: 4, ... }
updateData(doc, { "+[]tags": "c" }); // { ..., tags: ["a", "b", "c"] }
updateData(doc, { "-[]tags": "a" }); // { ..., tags: ["b"] }
updateData(doc, { "+[]tags": ["c", "d"] }); // add multiple at onceimport { updateData } from "shelving/util";
const doc = { user: { name: "Alice", score: 10 } };
updateData(doc, { "=user.name": "Bob" }); // { user: { name: "Bob", score: 10 } }
updateData(doc, { "+=user.score": 5 }); // { user: { name: "Alice", score: 15 } }import { getUpdates } from "shelving/util";
getUpdates({ "+=count": 1, "-[]tags": "old" });
// [
// { action: "sum", key: ["count"], value: 1 },
// { action: "omit", key: ["tags"], value: ["old"] },
// ]Decode the prop updates in an Updates object into a set of Update objects.
getUpdates(data: Updates<T>): ImmutableArray<Update>
Return a copy of a data object with a set of updates applied.
updateData(data: T, updates: Updates<T>): T
Set of named updates for a data object, keyed by encoded update syntax.
{
/**
* Set update (all branches)
* - Can set `a` and `a.a1` in `{ a: { a1: 123 } }`
* - Sometimes inference gets confused, if that happens use `=` syntax instead.
*/
readonly [K in BranchDataPath<T> as `${K}`]?: BranchData<T>[K] | undefined;
} & {
/**
* Set update (leaves only)
* - Can set `a.a1` in `{ a: { a1: 123 } }`, but cannot set `a`
* - Deeply-nested properties don't always infer when leaves and branches are combined.
* - This syntax is more exact and will infer better.
*/
readonly [K in LeafDataPath<T> as `=${K}`]?: LeafData<T>[K] | undefined;
} & {
/**
* Sum update.
* - Increment/decrement numbers.
*/
readonly [K in LeafDataPath<T> as `+=${K}` | `-=${K}`]?: LeafData<T>[K] extends number ? LeafData<T>[K] | undefined : never;
} & {
/**
* With/omit update.
* - Add or remove items from arrays.
*/
readonly [K in LeafDataPath<T> as `+[]${K}` | `-[]${K}`]?: LeafData<T>[K] extends ImmutableArray<unknown>
? LeafData<T>[K] | LeafData<T>[K][number] | undefined
: never;
}A single decoded update to a keyed property in an object.
| { action: "set"; key: Segments; value: unknown } //
| { action: "with"; key: Segments; value: ImmutableArray<unknown> } //
| { action: "omit"; key: Segments; value: ImmutableArray<unknown> } //
| { action: "sum"; key: Segments; value: number }