javascript
35 lines · 7 steps
Deep cloning with structuredClone
How to build safe deep copies with structuredClone, including capability checks and cloner-aware error handling.
Explained by
highlit
1export function cloneState(state) {
2 if (typeof structuredClone !== "function") {
3 throw new Error("structuredClone is not available in this runtime");
4 }
5
6 try {
7 return structuredClone(state);
8 } catch (err) {
9 if (err instanceof DOMException && err.name === "DataCloneError") {
10 throw new TypeError(
11 "State contains non-cloneable values (functions, DOM nodes, or class instances with private fields)",
12 { cause: err }
13 );
14 }
15 throw err;
16 }
17}
18
19export function withTransferables(payload, transfer) {
20 return structuredClone(payload, { transfer });
21}
22
23export function snapshotStore(store) {
24 const draft = {
25 entities: store.entities,
26 filters: new Map(store.filters),
27 lastFetched: new Date(store.lastFetched),
28 pending: new Set(store.pending),
29 buffer: store.buffer,
30 };
31
32 const clone = structuredClone(draft);
33 Object.freeze(clone);
34 return clone;
35}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1structuredClone deep-copies Maps, Sets, Dates, and typed arrays that JSON round-tripping would silently destroy.
- 2Cloning throws a DataCloneError DOMException for functions, DOM nodes, and other non-serializable values, so guard for it.
- 3Pairing a clone with Object.freeze yields an isolated, tamper-proof snapshot of mutable state.
Related explainers
php
<?php namespace App\Http\Requests\DataObjects;
Typed request DTOs in Laravel
data-transfer-object
validation
immutability
Intermediate
6 steps
javascript
import { useCallback, useEffect, useState } from 'react'; export function useLocalStorage(key, initialValue) { const readValue = useCallback(() => {
How a useLocalStorage hook syncs state in React
custom hooks
localstorage
state persistence
Intermediate
8 steps
python
from fastapi import FastAPI, Request, status from fastapi.encoders import jsonable_encoder from fastapi.exceptions import RequestValidationError from fastapi.responses import JSONResponse
Redacting sensitive fields in FastAPI errors
validation
error-handling
security
Intermediate
7 steps
javascript
import { useState } from 'react'; export function ReorderableList({ initialItems }) { const [items, setItems] = useState(initialItems);
Drag-to-reorder lists in React
drag-and-drop
state-management
immutable-updates
Intermediate
8 steps
java
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.module.SimpleModule;
Serializing Money to JSON in Spring
serialization
jackson
money
Intermediate
8 steps
php
<?php namespace App\Services;
Building a valid iCalendar feed in PHP in Laravel
ical
serialization
formatting
Intermediate
8 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/deep-cloning-with-structuredclone-explained-javascript-f109/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.