# Copying versus Structural Sharing — Functional Programming Concepts

Source: https://www.geekswithgeeks.com/en/functional-programming/im-sharing

> Spread, persistent data structures and Immer.

## Shallow copies and shared structure

The spread syntax (`{...obj}`, `[...arr]`) makes a **shallow copy**: top-level properties are copied, nested objects are still shared by reference. For a nested update you copy each level along the path and reuse everything else; this is **structural sharing**, and it is safe precisely because nothing is mutated. **Persistent data structures** (for example the tries used by Clojure, Scala and libraries such as Immutable.js) do this automatically and make updates to large collections cheap. **Immer** lets you write code that looks like mutation on a draft and produces a new immutable value with structural sharing.

## Nested update by hand and with Immer

Only the changed path is copied.

```typescript
type State = {
  user: { name: string; address: { city: string; zip: string } };
  cart: string[];
};

// By hand: copy each level along the path
function moveTo(state: State, city: string): State {
  return {
    ...state,
    user: {
      ...state.user,
      address: { ...state.user.address, city },
    },
  };
  // state.cart is reused (shared), not copied
}

// With Immer (npm package "immer"): write against a draft
import { produce } from 'immer';
const moveTo2 = (state: State, city: string) =>
  produce(state, draft => {
    draft.user.address.city = city;
  });
```

## structuredClone is not structural sharing

`structuredClone` makes a deep copy of everything, which is safe but allocates the whole tree. Prefer path copying or Immer for state updates.

**Quiz:** After `const b = { ...a }`, what is true of a nested object `a.inner`?

- [ ] `b.inner` is a deep copy
- [x] `b.inner` is the same object as `a.inner`
- [ ] `b.inner` is undefined
- [ ] `a.inner` is frozen

*Answer:* `b.inner` is the same object as `a.inner`. Spread copies only one level.
