Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rule request: prefer-object-spread #7230

Closed
ljharb opened this issue Sep 24, 2016 · 32 comments
Closed

Rule request: prefer-object-spread #7230

ljharb opened this issue Sep 24, 2016 · 32 comments
Assignees
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion archived due to age This issue has been archived; please open a new issue for any further discussion feature This change adds a new feature to ESLint rule Relates to ESLint's core rules

Comments

@ljharb
Copy link
Sponsor Contributor

ljharb commented Sep 24, 2016

Please describe what the rule should do:
When it finds an Object.assign call where the first argument is an object literal, the rule should error, and recommend using the object spread operator instead.

What category of rule is this? (place an "X" next to just one item)

[ ] Enforces code style
[ ] Warns about a potential error
[x] Suggests an alternate way of doing something
[ ] Other (please specify:)

Provide 2-3 code examples that this rule will warn about:

return Object.assign({}, foo, { bar: baz }, quux); // should be `return { ...foo, bar: baz, ...quux };`
return Object.assign({ foo }, bar, { baz }); // should be `return { foo, ...bar, baz };`

return Object.assign(foo, bar, { baz }); // should not warn

Why should this rule be included in ESLint (instead of a plugin)?
Just like http://eslint.org/docs/rules/prefer-spread, this recommends that users use a syntax feature (an operator) instead of API (Object.assign) for the cases where it makes sense. Both are core language features, and eslint core should be where core language feature rules live.

@eslintbot eslintbot added the triage An ESLint team member will look at this issue soon label Sep 24, 2016
@platinumazure
Copy link
Member

Object spread is still stage 2, right? It's one thing for us to have the parser option, but I'm not sure if we want to have rules around it just yet.

@platinumazure platinumazure added rule Relates to ESLint's core rules feature This change adds a new feature to ESLint evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion and removed triage An ESLint team member will look at this issue soon labels Sep 24, 2016
@ljharb
Copy link
Sponsor Contributor Author

ljharb commented Sep 24, 2016

@platinumazure yes, it's still stage 2. My hope is that it will achieve stage 3 next week - at that point, would it be OK to have the rule?

@platinumazure
Copy link
Member

platinumazure commented Sep 24, 2016

Well, our policy is usually to wait until stage 4 (cf. async/await), but given that we have a parser option already... I have no idea what might happen in this case. 😄

@not-an-aardvark
Copy link
Member

In my opinion, this might be better as an object option for prefer-spread rather than a new rule, since it's enforcing a similar thing and the name prefer-spread applies to both.

@ljharb
Copy link
Sponsor Contributor Author

ljharb commented Sep 25, 2016

@not-an-aardvark that would be totally fine too! As long as there's a way to enforce it.

@vitorbal
Copy link
Member

I think a new option for prefer-spread is a great idea, I'd get behind that.
But, like @platinumazure said, I just don't know if we're ready to add object spread support for rules or does the team prefer to wait until it reaches stage 4.

@ljharb
Copy link
Sponsor Contributor Author

ljharb commented Sep 30, 2016

As of this week, object rest/spread is stage 3, so it's just a matter of time :-)

@nzakas
Copy link
Member

nzakas commented Oct 1, 2016

At first glance, this seems more appropriate as a custom rule. prefer-spread is a very narrow use case right now, and these changes don't fit well there. I'm also not sure about the relationship between Object.assign and spread properties as something that is generic enough to be included in core.

So, Id suggest creating a custom rule for this.

@ljharb
Copy link
Sponsor Contributor Author

ljharb commented Oct 1, 2016

@nzakas spread props are, by spec, a 1:1 mapping to "Object.assign with an empty object literal as the target argument"

@nzakas
Copy link
Member

nzakas commented Oct 3, 2016

@ljharb I get that. My point is that I'm not sure there's much of a value proposition for using spread properties instead of Object.assign, whereas there's a big value proposition for using spread arguments instead of relying on .apply() to call a function with an array of arguments (eliminates some indirection).

Since we have a very high bar for including rules in the core, we really look for rules that have an obvious and easily discernible value proposition to end users. I just don't feel like this proposal meets that high bar.

@ljharb
Copy link
Sponsor Contributor Author

ljharb commented Oct 3, 2016

The value is that it's syntax, instead of API, so it's a) harder to mess up (ie, by forgetting to pass an empty object as the first argument, thus accidentally mutating the first argument), and b) easier for engines to optimize.

@ljharb
Copy link
Sponsor Contributor Author

ljharb commented Oct 3, 2016

Avoiding accidental mutation imo is a pretty high value prop, much higher than enforcing indentation or trailing commas (which are also important, ofc), to name a few :-/

@nzakas
Copy link
Member

nzakas commented Oct 7, 2016

@ljharb I understand that you feel it's important and useful, and the good news is that you can make this rule for yourself. I still don't see it as important enough to be in core at this point.

@ljharb
Copy link
Sponsor Contributor Author

ljharb commented Oct 7, 2016

I don't understand that - why is prefer-spread important enough to include, but prefer-object-spread not? They're both equivalent - shorter syntactic forms of API, that help avoid footguns, and indirection.

@not-an-aardvark
Copy link
Member

I agree with @ljharb that this rule would be a good idea, but I think it would be better as an additional option for prefer-spread rather than a separate rule as prefer-object-spread. I think being able to discourage Object.assign in favor of spread properties is just as notable as being able to discourage Function.prototype.apply in favor of spread elements.

@nzakas
Copy link
Member

nzakas commented Oct 7, 2016

@ljharb I've already explained my position in a previous comment. And as our guidelines say, we are being very picky about new rules because we already have way too many in the core and people find it daunting.

If other team members feel strongly about it, I'll withdraw my objection. Just, to me, this is one of those preferences that offers no clear benefit to users. It's a stylistic preference for a feature that isn't yet included in the spec, and as such, I have a hard time rationalizing its inclusion.

@not-an-aardvark
Copy link
Member

I suppose there are two independent questions here:

  • Are we comfortable introducing rule options that depend on stage 3 features? I have no strong opinion on this; one could argue that we would be better off waiting for stage 4, to minimize issues if the spec ends up changing.
  • Setting aside the status as a proposal (i.e. pretending it was stage 4), is this option beneficial enough to include in core? I think it is. We already have a rule called prefer-spread that does basically the same thing with spread elements. Adding an option to that rule to prefer spread properties as well seems like a very natural extension.

@nzakas nzakas added the tsc agenda This issue will be discussed by ESLint's TSC at the next meeting label Oct 13, 2016
@btmills
Copy link
Member

btmills commented Oct 13, 2016

The TSC decided in the 2016-10-13 meeting not to accept this option into core.

@btmills btmills closed this as completed Oct 13, 2016
@btmills btmills removed the tsc agenda This issue will be discussed by ESLint's TSC at the next meeting label Oct 13, 2016
@btmills
Copy link
Member

btmills commented Oct 13, 2016

Speaking for myself, I would use this if someone were to implement it in a plugin!

@ljharb
Copy link
Sponsor Contributor Author

ljharb commented Oct 13, 2016

whoa, can we get some more context on this decision?

@not-an-aardvark
Copy link
Member

not-an-aardvark commented Oct 13, 2016

@ljharb The meeting archive is here (discussion starts at 49 minutes after the hour).

@ljharb
Copy link
Sponsor Contributor Author

ljharb commented Oct 14, 2016

Thanks - I find that very sad. There is a clear level of indirection and footgun this avoids, which is "forgetting to use {} as the first argument, and accidentally mutating instead of creating a new object".

@bregenspan
Copy link

bregenspan commented Nov 1, 2017

Just for anyone finding this discussion through search, there is a plugin available for this here.

@ljharb
Copy link
Sponsor Contributor Author

ljharb commented Jan 25, 2018

Object rest/spread is now stage 4 (#9885), perhaps this could be reopened?

@mysticatea mysticatea reopened this Jan 25, 2018
@mysticatea
Copy link
Member

I'll champion this proposal, new prefer-object-spread rule. The advisory rule for new syntax would be helpful. TSLint looks to have the rule.

@mysticatea mysticatea self-assigned this Feb 5, 2018
@ljharb
Copy link
Sponsor Contributor Author

ljharb commented Feb 5, 2018

@mysticatea we already have an implementation of this rule internally at @airbnb, mind if we submit a PR?

@alberto
Copy link
Member

alberto commented Feb 6, 2018

@ljharb go ahead, but keep in mind the issue is not accepted yet. There was an ongoing conversation on the scope of the rule that I think still has to be resolved

@platinumazure platinumazure added accepted There is consensus among the team that this change meets the criteria for inclusion and removed evaluating The team will evaluate this issue to decide whether it meets the criteria for inclusion labels Feb 6, 2018
@platinumazure
Copy link
Member

Added a 👍 so this should theoretically be accepted now.

@alberto What discussion are we having about scoping? I seem to have missed that.

@alberto
Copy link
Member

alberto commented Feb 7, 2018

@platinumazure i was talking about @not-an-aardvark comment #7230 (comment)

sharmilajesupaul added a commit to sharmilajesupaul/eslint that referenced this issue Apr 13, 2018
@stevenvachon
Copy link
Contributor

...

@ljharb
Copy link
Sponsor Contributor Author

ljharb commented May 2, 2018

@stevenvachon that’s a wildly unhelpful comment; there’s an open PR and it’s being worked on.

ilyavolodin pushed a commit that referenced this issue May 11, 2018
* New: Adds prefer-object-spread rule (refs: #7230)

* Adds exception for `Object.assign` with one object literal argument

This was an exception to this rule that we use internally, in the case that an
`Object.assign` call is made with an object literal as the only argument. The
`Object.assign` call is not needed and we can just use the object literal
directly.

* Refactors and adds multiline object fixes

* Many fixes and improvements:
- handles nested object literals
- handles various comment types
- places comma after arguments in a smarter way

* Fixes typo and improves wording in docs

* include string.prototype.matchall in package.json

* Several improvements:

- adds line and column numbers to tests
- warn on cases where argument is a spread element,
- use getCommentsInside instead of regex
- fix example in doc

* use spread instead of apply

* Check if the native `Object` is being overwritten, if it is, do not warn.

Bug fix to ensure that an we're warning on an `Object.assign` for the literal case.

* make messages consistent
@mysticatea
Copy link
Member

Closing as #9955 was merged.

@eslint-deprecated eslint-deprecated bot locked and limited conversation to collaborators Dec 10, 2018
@eslint-deprecated eslint-deprecated bot added the archived due to age This issue has been archived; please open a new issue for any further discussion label Dec 10, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion archived due to age This issue has been archived; please open a new issue for any further discussion feature This change adds a new feature to ESLint rule Relates to ESLint's core rules
Projects
None yet
Development

No branches or pull requests