eslint / eslint

Find and fix problems in your JavaScript code.
https://eslint.org
MIT License
24.39k stars 4.4k forks source link

New Rule: prefer-structured-clone #18354

Closed kirkwaiblinger closed 1 month ago

kirkwaiblinger commented 1 month ago

Rule details

Report on older patterns for cloning an object

Related ECMAScript feature

structuredClone

What type of rule is this?

Suggests an alternate way of doing something

Example code

var clonedObject = JSON.parse(JSON.stringify(thingToBeCloned));
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
/* suggest to */
var clonedObject = structuredClone(thingToBeCloned);

// not equivalent, but often used for the same purpose. Possibly could be behind an option? Certainly not autofixable.
var clonedObject = { ...thingToBeCloned };
                   ^^^^^^^^^^^^^^^^^^^^^^
var clonedObject = Object.assign({}, thingToBeCloned);
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Why should this rule be in the core instead of a plugin?

This addresses a (relatively) newly available language feature that is much more robust than standard approaches in widespread use.

Participation

Additional comments

docs on structuredClone: https://developer.mozilla.org/en-US/docs/Web/API/structuredClone.

As far as I can tell, it will always work identically for things able to be faithfully cloned by JSON.parse(JSON.stringify(x)).

It will additionally handle several built-in classes (e.g. RegExp, Error, Map, Set, TypedArray), and can handle circular structures.

For things that are unfaithfully cloned by JSON cloning, either because they ignore properties, or because some properties have a weird JSON representation (TypedArray), the structuredClone equivalent will produce different (more faithful) results.

nzakas commented 1 month ago

Thanks for the suggestion. I don't think this makes for a good core rule for a couple reasons:

  1. structuredClone() is not part of ECMA-262, it's part of HTML, which means that there's no guarantee a JavaScript runtime will implement it even if it does formally support JavaScript.
  2. The results will not always be the same as the alternatives. In general, our "prefer" core rules flag different ways of producing the same results, and I think it's dangerous to start doing so when the results may not be the same.

That said, you could definitely make this as a custom rule in a plugin. I'm sure some will find it useful.

fisker commented 1 week ago

Implemented in eslint-plugin-unicorn, but I don't think the shallow copy cases make sense to report.