[Solved] structuredClone is not defined in JS and Node.js

avatar
Borislav Hadzhiev

Last updated: Apr 5, 2024
6 min

banner

# Table of Contents

  1. structuredClone is not defined in JS and Node.js
  2. Using the JSON.stringify() and JSON.parse() methods
  3. Using the lodash.cloneDeep method instead
  4. Update your typings if you use TypeScript
  5. Update Node.js to the long-term supported version
  6. Jest and JSDOM: structuredClone is not defined

NOTE: if you got the error when using JEST and JSDOM, click on the following subheading:

# [Solved] structuredClone is not defined in JS and Node.js

The "ReferenceError: structuredClone is not defined" error occurs when you use the structuredClone() method in an older Node.js environment.

To solve the error, make sure you're running Node.js version 17 or greater.

referenceerror structuredclone is not defined

As shown in this table, the structuredClone method was introduced in Node.js version 17.0.0.

You can use the node -v command to get your version of Node.js.

shell
node -v

get node version 14

If you try to run the following code sample with Node < 17, the error occurs.

index.js
const obj = { first: 'bobby', last: 'hadz', address: { country: 'Country 123', city: 'City 123', }, }; // โ›”๏ธ ReferenceError: structuredClone is not defined console.log(structuredClone(obj));

The structuredClone method is used to create a deep clone of the supplied object.

There are 3 common ways to solve the error:

  1. Update Node.js to the long-term supported version.
  2. Use the JSON.stringify() and JSON.parse() methods to create a deep clone of the object.
  3. Use the lodash.cloneDeep method.

NOTE: if you got the error when using JEST and JSDOM, click on the following subheading:

# Using the JSON.stringify() and JSON.parse() methods

There is a hacky way to create a deep clone of an object using the JSON.stringify and JSON.parse methods.

index.js
const obj = { first: 'bobby', last: 'hadz', address: { country: 'Country 123', city: 'City 123', }, }; const deepCopy = JSON.parse(JSON.stringify(obj)); // { // first: 'bobby', // last: 'hadz', // address: { country: 'Country 123', city: 'City 123' } // } console.log(deepCopy);
  1. The JSON.stringify() method is used to convert the object to a JSON string.
  2. By converting the object to a string, the nested objects lose their reference.
  3. The JSON.parse() method is used to convert the JSON string to an object.

This works because when the object gets converted to a string, the references to the nested objects are lost.

index.js
const obj = { first: 'bobby', last: 'hadz', address: { country: 'Country 123', city: 'City 123', }, }; const deepCopy = JSON.parse(JSON.stringify(obj)); deepCopy.address.city = 'New city'; console.log(deepCopy.address.city); // ๐Ÿ‘‰๏ธ New City // โœ… The original remains unchanged console.log(obj.address.city); // ๐Ÿ‘‰๏ธ City 123

As shown in the code sample, modifying a nested property in the copied object doesn't modify the property in the original object.

# Using the lodash.cloneDeep method instead

There are some issues with using the JSON.parse() and JSON.stringify() methods - mainly around objects that recursively reference themselves.

An alternative approach is to use the lodash.clonedeep method.

You can install the module by running the following commands.

shell
# ๐Ÿ‘‡๏ธ with NPM npm install lodash.clonedeep # ๐Ÿ‘‡๏ธ Only if you use TypeScript npm install --save-dev @types/lodash.clonedeep # ------------------------------------------ # ๐Ÿ‘‡๏ธ with YARN yarn add lodash.clonedeep # ๐Ÿ‘‡๏ธ Only if you use TypeScript yarn add @types/lodash.clonedeep --dev

After you install the module, import and use the cloneDeep method.

index.js
import cloneDeep from 'lodash.clonedeep'; // ๐Ÿ‘‡๏ธ Uncomment this if you use require() // const cloneDeep = require('lodash.clonedeep'); const obj = { first: 'bobby', last: 'hadz', address: { country: 'Country 123', city: 'City 123', }, }; const deepCopy = cloneDeep(obj); // { // first: 'bobby', // last: 'hadz', // address: { country: 'Country 123', city: 'City 123' } // } console.log(deepCopy);

If you use CommonJS, use the require() import statement instead.

The cloneDeep method recursively clones the supplied value and returns the result.

Changing a nested property in the cloned object doesn't change the property in the original object.

index.js
import cloneDeep from 'lodash.clonedeep'; const obj = { first: 'bobby', last: 'hadz', address: { country: 'Country 123', city: 'City 123', }, }; const deepCopy = cloneDeep(obj); deepCopy.address.city = 'New city'; console.log(deepCopy.address.city); // ๐Ÿ‘‰๏ธ New City // // โœ… The original remains unchanged console.log(obj.address.city); // ๐Ÿ‘‰๏ธ City 123

We changed the value of the address.city property in the cloned object but the original object remains the same.

# Update your typings if you use TypeScript

If you use TypeScript, make sure you have a recent version of the @types/node package installed.

shell
# with NPM npm install @types/node@latest --save-dev # with YARN yarn add @types/node@latest --dev

You can also update your version of typescript if the installed module is out of date.

shell
# with NPM npm install typescript@latest --save-dev # with YARN yarn add typescript@latest --dev

# Update Node.js to the long-term supported version

As previously noted, the structuredClone method was introduced in Node.js version 17.0.0.

If the output of the node -v command is less than 17, then you have to install the long-term supported version of Node.js.

One way to install the LTS Node.js version is to use the official Node.js website.

referenceerror structuredclone is not defined

At the time of writing the LTS Node.js version is 18.15.0 where the structuredClone method is available.

download node lts version

Here are other examples of packages that enable you to manage your Node.js version:

For example, if you install the nvm for macOS and Linux package, you can use the following commands to switch to the LTS version.

shell
# NVM for macOS and Linux nvm install --lts nvm use --lts

nvm macos linux switch lts

If you install the nvm for Windows package, use the following commands instead.

shell
# NVM for Windows nvm install lts nvm use lts

nvm windows switch to lts

Want to learn more about installing and using NVM? Check out these resources: Install NVM on macOS and Linux,Install NVM on Windows.

If you install the n package, use the following commands.

shell
# using n package npm install -g n n lts

If you install the volta package, use the following commands.

shell
# using the Volta package volta install node

If you use Chocolatey on Windows:

  1. Click on the Search bar and type CMD.

  2. Right-click on the Command Prompt application and click "Run as administrator".

windows run cmd as administrator

  1. Run the following command to install the LTS Node.js version.
shell
choco install nodejs --version=18.5.0

chocolatey install node lts

You can issue the node -v command to verify your version of Node.js is greater than 17.

You can use the structuredClone method if your Node.js version is 17 or greater.

index.js
const obj = { first: 'bobby', last: 'hadz', address: { country: 'Country 123', city: 'City 123', }, }; console.log(structuredClone(obj));

using structured clone method

# Jest and JSDOM: structuredClone is not defined

If you got the "structuredClone is not defined" error when working in jest and jsdom, use a polyfill.

Open your terminal and run the following command to install the @ungap/structured-clone package.

shell
npm install @ungap/structured-clone # ๐Ÿ‘‡๏ธ only if you use TypeScript npm install --save-dev @types/ungap__structured-clone

Open your jest.config.js or jest.config.ts file and set the structuredClone global.

jest.config.js
import structuredClone from '@ungap/structured-clone' export default { // ... rest of your config globals: { structuredClone, }, };

Alternatively, you can import the structuredClone polyfill in the files where the method is used.

# Extending the JSDOMEnvironment class to solve the error

An alternative approach to solving the error is to extend from the JSDOMEnvironment class and set the structuredClone global.

In the root directory of your project, right next to jest.config.js, create a file called JSDOMEnvironmentPatch.js and add the following code to it.

JSDOMEnvironmentPatch.js
import JSDOMEnvironment from 'jest-environment-jsdom'; export default class JSDOMEnvironmentPatch extends JSDOMEnvironment { constructor(...args) { super(...args); this.global.structuredClone = structuredClone; } }

Update the testEnvironment property in your jest.config.js class.

jest.config.js
module.exports = { testEnvironment: './JSDOMEnvironmentPatch.js', // ... rest of your config };

Here is the TypeScript equivalent of the file.

JSDOMEnvironmentPatch.ts
import JSDOMEnvironment from 'jest-environment-jsdom'; export default class JSDOMEnvironmentPatch extends JSDOMEnvironment { constructor( ...args: ConstructorParameters<typeof JSDOMEnvironment> ) { super(...args); this.global.structuredClone = structuredClone; } }

Make sure to correct the extension when setting thetestEnvironment property if you use TypeScript.

jest.config.js
module.exports = { testEnvironment: './JSDOMEnvironmentPatch.ts', // ... rest of your config };

Make sure you have the jest-environment-jsdom module installed.

shell
# with NPM npm install --save-dev jest-environment-jsdom # with YARN yarn add jest-environment-jsdom --dev

After you set the structuredClone global to the actual method, the error should be resolved.

# Using a monkey patch solution in Jest and JSDOM

An alternative approach is to monkey patch the structuredClone global.

For example, you can create a file called structuredClonePatch.js with the following contents.

structuredClonePatch.js
if (!global.structuredClone) { global.structuredClone = function structuredClone(obj) { return JSON.parse(JSON.stringify(obj)); }; }

And import the file in the entry point of your application (e.g. index.js or index.ts).

index.js
import './structuredClonePatch.js'

The file has to be imported before any references to the structuredClone global method.

We simply check if the method doesn't exist on the global object.

If the condition is met, we set the global to the combination of JSON.parse() and JSON.stringify() instead.

Alternatively, you can mock the structuredClone method in your test file.

index.test.js
global.structuredClone = jest.fn(val => { return JSON.parse(JSON.stringify(val)); });

You should generally stick to the polyfill solution or extend the JSDOMEnvironment environment class, however, if nothing else works, monkey patching or mocking the method gets the job done.

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2025 Borislav Hadzhiev