Skip to content

feat(atoms): replace arrays instead of deep merging in mutate shorthand#358

Merged
bowheart merged 1 commit intomasterfrom
josh/proxy-shorthand-arrays
Mar 5, 2026
Merged

feat(atoms): replace arrays instead of deep merging in mutate shorthand#358
bowheart merged 1 commit intomasterfrom
josh/proxy-shorthand-arrays

Conversation

@bowheart
Copy link
Collaborator

@bowheart bowheart commented Mar 5, 2026

Summary

  • Arrays in .mutate shorthand now fully replace instead of deep merging by index. The previous behavior was surprising — e.g. signal.mutate({ arr: [1, 2] }) on state { arr: [10, 20, 30] } produced { arr: [1, 2, 30] }. Now it produces { arr: [1, 2] }. The callback form still supports index-level updates: signal.mutate(s => { s.arr[2] = 30 })
  • Fixes pre-existing type errors in AtomInstance, AtomTemplate, AtomTemplateBase, atom.ts, and ion.ts by loosening the AtomApiGenerics Signal constraint from bare Signal to AnySignal (Signal<any>)
  • Consolidates RecursivePartialWithArrayPlucking into RecursivePartial — adds an array guard to RecursivePartial in both @zedux/core and @zedux/atoms so arrays are treated as leaf values instead of having their methods made optional

This reverts the array pluck shorthand introduced in v2.0.0-rc.13 from #331 6 days ago, so I'm not too concerned about it breaking stuff. Now that .mutate shorthands can overwrite values with different value types (e.g. objects replacing arrays and vice versa), the pluck shorthand is strange. It's better to use normal mutation in the callback form for updating individual array elements anyway.

Test plan

  • All 45 proxy integration tests pass with updated expectations
  • tsc --noEmit passes with zero errors for the atoms package
  • Verify no regressions in downstream consumer code that relied on array deep merge behavior

🤖 Generated with Claude Code

@bowheart bowheart force-pushed the josh/proxy-shorthand-arrays branch from 8544ea4 to cef302d Compare March 5, 2026 21:44
Arrays in the `.mutate` shorthand now fully replace instead of deep
merging by index. The previous behavior was surprising - e.g.
`signal.mutate({ arr: [1, 2] })` on `[10, 20, 30]` would produce
`[1, 2, 30]`. Now it produces `[1, 2]`. Use the callback form for
index-level updates: `signal.mutate(s => { s.arr[2] = 30 })`.

Also fixes pre-existing type errors by loosening `AtomApiGenerics`
Signal constraint from `Signal` to `AnySignal`, and consolidates
`RecursivePartialWithArrayPlucking` into `RecursivePartial` (with an
array guard added to both core and atoms).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@bowheart bowheart force-pushed the josh/proxy-shorthand-arrays branch from cef302d to 0007df1 Compare March 5, 2026 21:45
@bowheart bowheart merged commit 4e58386 into master Mar 5, 2026
2 checks passed
@bowheart bowheart deleted the josh/proxy-shorthand-arrays branch March 5, 2026 21:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant